Соответствует ли / abcd ^ $ / i чему-либо в Perl? - PullRequest
3 голосов
/ 19 июля 2009

Perl - это одна из тех вещей, в которые у меня никогда не было достаточных оснований. К сожалению, у меня есть очень специфический (на мой взгляд, ошибка) фрагмент кода Perl, и мне нужно определить его операцию доказуемо .

Этот код написан и уже находится в производстве, я хочу удалить его.

Я считаю, что невозможно успешно сопоставить, но это одна из тех вещей, что предположение по этому вопросу (особенно мое) недостаточно. Он защищает блок кода {}, который, к сожалению, имеет несколько условий, поэтому может быть введен независимо от состояния этого выражения, но есть проблема безопасности, если это происходит (ошибка сама по себе, если состояние не определено, IMHO, все же без доказательств, что воздействие / серьезность ниже (читай, никогда не исправишься)).

Возможно ли /abcd^$/i до когда-либо , совпадение успешно? Включая вставку нулевого байта или любые возможные байтовые / двоичные данные? Я бы даже пошел с какой-то безумной атакой на окружение (например, потребляя всю память на хосте в пределах 1 байта, что приводило к тому, что оценщик выражений Perl не выполнял непроверенное 2-байтовое выделение во время выполнения). Престижность для творчества.

Ответы [ 5 ]

6 голосов
/ 19 июля 2009

Из справочной страницы perlre:

Однако вы можете пожелать рассматривать строку как многострочный буфер, такой, что «^» будет соответствовать после любой новой строки внутри строки (кроме случаев, когда символ новой строки является последним символом в строка), и "$" будет соответствовать перед любой новой строкой. За счет немного больше накладных расходов, вы можете сделать это с помощью модификатора / m на оператор сопоставления с образцом. (Старые программы делали это путем установки $ *, но эта практика была удалена в Perl 5.9.)

Поэтому убедитесь, что $ * или, возможно, другие предопределенные переменные не мешают.

Тем не менее, даже $ * модифицированное выражение типа / abcd ^ $ / im (обратите внимание на добавленный флаг "m") не будет ничего совпадать, потому что символ "^" соответствует только после новой строки.


Кроме того, убедитесь, что регулярное выражение не перегружено. Если импортированный пакет делает что-то вроде этого:

use overload;                                                                   
sub import {                                                                    
    overload::constant(qr => sub { $_ = shift; s/^abcd//; $_ });                 
} 

Тогда пустые строки будут соответствовать вашему регулярному выражению.


Кроме того, не знаю, является ли это регулярным выражением в вашем коде, и оно может быть неактуальным, но просто чтобы быть в безопасности, вы не должны неявно сопоставлять $ _, а явно указывать переменную: "$ str = ~ /abcd^$/i;".

$ _ имеет динамическую область видимости, поэтому, если у вас есть какие-либо вызовы функций, которые могут изменить $ _ в зависимости от того, где вы его определяете и где находится регулярное выражение, или если вы добавите их позже, вас ждет сюрприз:)

4 голосов
/ 21 июля 2009

Кстати, я думал, что укажу use re 'debug' здесь. Вы можете использовать его, чтобы увидеть, как Perl компилирует и сопоставляет ваши регулярные выражения:

$ perl -Mre=debugcolor -e '/abcd^$/'
Compiling REx "abcd^$"
Final program:
   1: EXACT <abcd> (3)
   3: BOL (4)
   4: EOL (5)
   5: END (0)
anchored "abcd"$ at 0 (checking anchored) minlen 4
Freeing REx: "abcd^$"

С м:

$ perl -Mre=debugcolor -e '/abcd^$/m'
Compiling REx "abcd^$"
Final program:
   1: EXACT <abcd> (3)
   3: MBOL (4)
   4: MEOL (5)
   5: END (0)
anchored "abcd"$ at 0 (checking anchored) minlen 4
Freeing REx: "abcd^$"

Вы также можете попробовать некоторые примеры данных и убедиться, что ничего не соответствует:

$ perl -Mre=debugcolor -e '"not going to match" =~ /abcd^$/m'
Compiling REx "abcd^$"
Final program:
   1: EXACT <abcd> (3)
   3: MBOL (4)
   4: MEOL (5)
   5: END (0)
anchored "abcd"$ at 0 (checking anchored) minlen 4
Guessing start of match in sv for REx "abcd^$" against "not going to match"
Did not find anchored substr "abcd"$...
Match rejected by optimizer
Freeing REx: "abcd^$"

Здесь совпадение заканчивается дважды:

$ perl -Mre=debug -e '"abcd\nabcd\n\n" =~ /abcd^$/m'
...
anchored "abcd"$ at 0 (checking anchored) minlen 4
Guessing start of match in sv for REx "abcd^$" against "abcd%nabcd%n%n"
Found anchored substr "abcd"$ at offset 0...
Guessed: match at offset 0
Matching REx "abcd^$" against "abcd%nabcd%n%n"
   0 <> <abcd%nabcd>         |  1:EXACT <abcd>(3)
   4 <abcd> <%nabcd%n%n>     |  3:MBOL(4)
                                  failed...
   5 <abcd%n> <abcd%n%n>     |  1:EXACT <abcd>(3)
   9 <abcd%nabcd> <%n%n>     |  3:MBOL(4)
                                  failed...
Match failed
Freeing REx: "abcd^$"

Попробуй запустить это сам, так как когда цвет от используется debugcolor.

Существует справочная страница .

4 голосов
/ 19 июля 2009

В чем смысл этого регулярного выражения? Возможно, он не выполняет свою работу правильно, и мы можем это исправить для вас. Какие данные он пытается сопоставить? Возможно ли, что оригинальный кодер пытался соответствовать буквальному ^? От каких ситуаций он защищает?

В подобных ситуациях я считаю, что лучше выяснить, что должно происходить в коде, а не что на самом деле происходит. Намерение может быть правильным, но реализация неправильной. Ошибки случаются. :)

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

1 голос
/ 02 января 2010

Документация perlre состояния

Встроенные символы новой строки не будут совпадать с ^ или $.

Литерал /abcd^$/ никогда не может совпадать, потому что ^ соответствует только в начале строки или после новой строки в многострочном режиме, поэтому ^$ в конце шаблона требует помощи, чтобы пройти встроенный перевод строки.

С более старым Perl могут совпадать похожие шаблоны:

$ cat prog
#! /usr/local/bin/perl -w

$* = 1;
$_ = "AbC\n\n";
print /abc\n^$/i  ? "Match.\n" : "No match.\n";
print /abc\s*^$/i ? "Match.\n" : "No match.\n";

$ ./prog
Use of $* is deprecated at ./prog line 3.
Match.
Match.

Обратите внимание на предупреждение об устаревании от древнего perl-5.6.1, а в версии 5.10.0 удалена поддержка $*. Возможно, но с патологической стороны.

1 голос
/ 19 июля 2009

/abcd^$/i совпадает с /abcd^$/im, если $* было установлено в значение true (в Perl до 5.9).

Я бы переписал это /abcd$^$/im.

По сути, он ищет 'abcd' в конце строки, за которым следует пустая строка.

За исключением того, что перед '^' должно быть что-то, что захватывает перевод строки.

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