Безопасно ли использовать memcpy regex_t? - PullRequest
1 голос
/ 24 июня 2019

Всегда ли работает простая, мелкая копия regex_t (из POSIX <regex.h> и regcomp() и т. Д.)?

Ответы [ 3 ]

8 голосов
/ 24 июня 2019

Гарантируется ли всегда простая, мелкая копия regex_t?

При условии, что объект, на который указывает указатель назначения, достаточно большой, чтобы содержать скопированные байты, и не перекрывает исходный объект, для memcpy() не определены условия сбоя. В той мере, в которой что-либо на компьютере может быть гарантировано, копия гарантированно будет успешной.

Однако, то, что не обязательно означает , означает, что полученная копия может использоваться независимо от оригинала. POSIX не предъявляет достаточных требований к regex_t, чтобы обеспечить это, и было бы не слишком удивительно, если бы некоторые реализации regex_t содержали указатели на динамически распределяемые данные. Фактически существование функции regfree() является явным условием для такой возможности.

2 голосов
/ 25 июня 2019

Спецификация POSIX здесь написана довольно плохо:

Если аргумент preg для regexec () или regfree () не является скомпилированным регулярным выражением, возвращаемым regcomp (), результат не определен.

preg это не объект, а указатель на объект (поэтому он должен сказать что-то вроде «не указывает на ...»), а regcomp не «возвращает» его (он изменяет к объекту), но намерение «есть», по-видимому, состоит в том, что это должен быть тот же объект, а не другой объект с тем же значением. Я бы интерпретировал вызов regfree для копии как нарушение этого, что привело бы к неопределенному поведению.

1 голос
/ 24 июня 2019

Можно интерпретировать POSIX так, что это нормально, но, вероятно, смело и неразумно.

В ISO C (который включен в POSIX с помощью нормативной справки) написано следующее точно об одном типе библиотеки, а не о другом:

"Адрес объекта FILE, используемого для управления потоком, может быть значительным; копия объекта FILE не должна служить вместо оригинала."

По сути, тот же текст повторяется в POSIX, 2.5 Стандартные потоки ввода / вывода.

Таким образом, вы могли бы подумать, что это создает прецедент "отказа": любое представление, которое не должно копироваться, будет задокументировано с таким запретом, а другие типы могут быть.

Кроме того, это подтверждается наличием явного отказа от участия в другой области стандарта: threading:

"Для барьеров, переменных условий, мьютексов и блокировок чтения-записи: [TSH] [Option Start], если для атрибута общего процесса установлено значение PTHREAD_PROCESS_PRIVATE, [Option End] только объект синхронизации по адресу используется для инициализации, может использоваться для выполнения синхронизации. "

Похоже, что стандартный подход состоит в том, чтобы разобрать, когда использование скопированного объекта запрещено.

Тем не менее, я бы с осторожностью скопировал любую структуру, которая служит своего рода указателем ресурса с сохранением состояния, а не просто информационной структурой (например, struct stat или struct pwent). Разработчики могут случайно сделать такую ​​вещь чувствительной к своему собственному адресу, например:

struct foo {
  type_t *internal_ptr;
  /* ... */
  type_t internal_array_of_something[...];
};

В POSIX нет текста, который запрещает это. Аналогичная проблема возникает, если система где-то поддерживает обратные указатели на структуру или внутри структуры.

POSIX должен читаться, в первую очередь, не как руководство по программированию (что программы могут или не могут делать), а как набор требований для реализации, которая принимает программы.

Не похоже, что в POSIX существует требование, согласно которому реализация не должна делать regex_t чувствительным к своему адресу. Если это так, это означает, что такая реализация не может не соответствовать.

То есть эта проблема подчеркивается в областях требований для FILE * потоков и pthread объектов синхронизации, которые могут не иметь никаких последствий для любых других областей.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...