Сравнение путей со специальными символами на Mac UTF-8

У нас есть kext, который проверяет, является ли путь подкаталогом другого пути, и творит чудеса, если это так.

Все это работает нормально, пока у нас нет специальных символов в нашем пути (таких как )

Мы передаем некоторые рабочие пути в систему с помощью вспомогательного приложения, которое может взаимодействовать с kext.

Я выделил проблему для этого кода:

#include <stdio.h>
#include <string.h>

int main ()
{
  char* path = "/Users/user/test/tëst/test"; //Sent by the system
  char* wp = "/Users/user/test/tëst"; //Some path we claim to be ours

  size_t wp_len = strlen(wp);

  if (strncmp (wp,path,wp_len) == 0) //Check is path is a subpath
  {
    printf ("matched %s\n", path);
  }else {
    printf ("could not match\n");

  }
  return 0;
}

Я создал Gist, поэтому кодировка не потеряется в браузере: https://gist.github.com/fvandepitte/ec28f4321a48061808d0095853af7bd7

Кто-нибудь знает, как я могу проверить, является ли path подпутью wp, не теряя при этом слишком много производительности (этот код работает в ядре)?


person Frederiek    schedule 07.11.2016    source источник
comment
developer.apple.com/library/content/qa/qa1173/_index. html   -  person n. 1.8e9-where's-my-share m.    schedule 07.11.2016


Ответы (1)


Я скопировал/вставил исходный код прямо из браузера в файл (test.c). Он печатает could not match для меня.

Если я выгружу файл с помощью od, я увижу следующее:

bash-3.2$ od -c test.c                                                     
0000000    #   i   n   c   l   u   d   e       <   s   t   d   i   o   .   
0000020    h   >  \n   #   i   n   c   l   u   d   e       <   s   t   r   
0000040    i   n   g   .   h   >  \n  \n   i   n   t       m   a   i   n   
0000060        (   )  \n   {  \n           c   h   a   r   *       p   a   
0000100    t   h       =       "   /   U   s   e   r   s   /   u   s   e   
0000120    r   /   t   e   s   t   /   t   ë  **   s   t   /   t   e   s   
0000140    t   "   ;       /   /   S   e   n   t       b   y       t   h   
0000160    e       s   y   s   t   e   m  \n           c   h   a   r   *   
0000200        w   p       =               "   /   U   s   e   r   s   /   
0000220    u   s   e   r   /   t   e   s   t   /   t   e    ̈  **   s   t   
0000240    "   ;       /   /   S   o   m   e       p   a   t   h       w   

Обратите внимание, что тест path выходит как t ë ** s t, но тест wp выходит как t e ̈ ** s t, что отличается: поэтому strncmp не сработает при сравнении ë и e.

Если я скопирую тест из path, вставлю его в задание wp, то получу matched /Users/user/test/tëst/test, так что strncmp работает нормально.

Я не знаю, что эти две строки так различаются, я могу только предположить, что эти две строки каким-то образом используют разные кодировки. Функция strncmp сравнивает строки на байт, поэтому ë и e ̈ считаются разными. Если вы хотите использовать strncmp, то, к сожалению, нет простого решения, кроме как убедиться, что обе строки используют одну и ту же кодировку.

FWIW — я использую macOS 10.12.1 с версией clang Apple LLVM версии 8.0.0 (clang-800.0.42.1)

EDIT: я скачал pathtest.cpp по вашей ссылке на github, чтобы перепроверить. Я запустил od -c pathtest.cpp и вижу ту же проблему.

person OLL    schedule 07.11.2016
comment
Спасибо за информацию, посмотрю, что @n.m. придумал. - person Frederiek; 07.11.2016
comment
После дальнейшего чтения и AHA-момента я могу сказать, что у нас есть предварительно составленные и разложенные персонажи. Каким-то образом мы храним разложенные значения в kext, и я думаю, что смогу исправить это там, где мы их храним. - person Frederiek; 08.11.2016