perlre长度限制

时间:2011-01-04 10:11:04

标签: perl regex

来自man perlre

  

“*”量词相当于“{0,}”,“+”量词相当于“{1,}”和“?”量词为“{0,1}”。 n和m限于小于建立perl时定义的预设限制的整数值。在最常见的平台上,这通常是32766。实际限制可以在代码生成的错误消息中看到,如下所示:

       $_ **= $_ , / {$_} / for 2 .. 42;

哎呀,这很丑陋 - 难道不是我可以得到一些常数吗?

编辑:正如daxim指出的那样(以及perlretut提示),32767可能是一个神奇的硬编码。 Perl代码中的一点searching有很长的路要走,但我不确定如何进入下一步并实际找到实际设置的默认reg_infty或REG_INFTY的位置:

~/dev/perl-5.12.2
$ grep -ri 'reg_infty.*=' *
regexec.c:      if (max != REG_INFTY && ST.count == max)
t/re/pat.t:        $::reg_infty   = $Config {reg_infty} // 32767;
t/re/pat.t:        $::reg_infty_m = $::reg_infty - 1;
t/re/pat.t:        $::reg_infty_p = $::reg_infty + 1;
t/re/pat.t:        $::reg_infty_m = $::reg_infty_m;   # Surpress warning.

编辑2:DVK当然是正确的:它在编译时是define d,并且可能只能用REG_INFTY覆盖。

1 个答案:

答案 0 :(得分:8)

总结:我有三种方法可以想到找到极限:经验,“匹配Perl测试”和“理论”。

  • 经验:

    eval {$_ **= $_ , / {$_} / for 2 .. 129};
    # To be truly portable, the above should ideally loop forever till $@ is true.
    $@ =~ /bigger than (-?\d+) /; 
    print "LIMIT: $1\n"'
    

    这似乎很明显,不需要解释。

  • 匹配Perl测试:

    Perl对正则表达式进行了一系列测试,其中一些(在pat.t中)处理测试这个最大值。因此,您可以估算出在这些测试中计算出的最大值“足够好”并遵循测试的逻辑:

    use Config;
    $reg_infty = $Config {reg_infty} // 2 ** 15 - 1; # 32767
    print "Test-based reg_infinity limit: $reg_infty\n";
    

    以下是对测试中基于何处的解释。

  • 理论:这是试图复制C代码使用的EXACT逻辑来生成此值。

    这听起来更难,因为它受到两件事的影响:Perl构建配置和一堆带有分支逻辑的C #define语句。我能够深入研究这个逻辑,但是在两个问题上停滞不前:#ifdefs引用了一堆令牌,这些令牌实际上并没有在我能找到的Perl代码中的任何地方定义 - 我不知道如何从Perl中找出那些define s值是什么,以及#ifdef的最终默认值(假设我是对的,#define PERL_USHORT_MAX ((unsigned short)~(unsigned)0)总是以默认值结束){通过删除产生全部数字的1位来获得实际限制 - 详情如下。

    我也不确定如何从Perl访问short中的字节数,无论用于构建perl可执行文件的实现是什么。

    所以,即使可以找到这两个问题的答案(我也不确定),结果逻辑肯定会比直接的“基于经验评估的”我更加“丑陋”和复杂。作为第一选择提供。

下面我将提供Perl代码中与此限制相关的各种逻辑部分的详细信息,以及我尝试获得与C逻辑匹配的“理论正确”解决方案。


好的,这是一些调查的一部分,你可以自己完成,因为我已经运行或者我将在稍后完成:

  • 来自regcomp.cvFAIL2("Quantifier in {,} bigger than %d", REG_INFTY - 1);

    因此,限制显然来自REG_INFTY定义。该声明在:

  • rehcomp.h

     /* XXX fix this description.
        Impose a limit of REG_INFTY on various pattern matching operations
        to limit stack growth and to avoid "infinite" recursions.
     */
     /* The default size for REG_INFTY is I16_MAX, which is the same as
        SHORT_MAX (see perl.h).  Unfortunately I16 isn't necessarily 16 bits
        (see handy.h).  On the Cray C90, sizeof(short)==4 and hence I16_MAX is
        ((1<<31)-1), while on the Cray T90, sizeof(short)==8 and I16_MAX is
        ((1<<63)-1).  To limit stack growth to reasonable sizes, supply a
        smaller default.
             --Andy Dougherty  11 June 1998
     */
     #if SHORTSIZE > 2
     #  ifndef REG_INFTY
     #    define REG_INFTY ((1<<15)-1)
     #  endif
     #endif
     #ifndef REG_INFTY
     #  define REG_INFTY I16_MAX
     #endif
    

    请注意SHORTSIZE可以通过Config覆盖 - 我会留下详细信息,但逻辑需要包含$Config{shortsize}:)

  • 来自handy.h(乍一看似乎不是Perl源码的一部分所以它看起来像是一个不确定的步骤):

     #if defined(UINT8_MAX) && defined(INT16_MAX) && defined(INT32_MAX)
     #define I16_MAX INT16_MAX
     #else
     #define I16_MAX PERL_SHORT_MAX
    
  • 我找不到定义INT16_MAX任何位置:(

    有人请帮忙!!!

  • PERL_SHORT_MAX在perl.h中定义:

     #ifdef SHORT_MAX
     #  define PERL_SHORT_MAX ((short)SHORT_MAX)
     #else
     #  ifdef MAXSHORT    /* Often used in <values.h> */
     #    define PERL_SHORT_MAX ((short)MAXSHORT)
     #  else
     #    ifdef SHRT_MAX
     #      define PERL_SHORT_MAX ((short)SHRT_MAX)
     #    else
     #      define PERL_SHORT_MAX      ((short) (PERL_USHORT_MAX >> 1))
     #    endif
     #  endif
     #endif
    

    到目前为止,我找不到任何定义SHORT_MAX,MAXSHORT或SHRT_MAX的地方。所以默认为((short) (PERL_USHORT_MAX >> 1)),现在假定它是:)

  • perl.h中,PERL_USHORT_MAX的定义非常相似,我再也无法找到USHORT_MAX / MAXUSHORT / USHRT_MAX的定义。

    这似乎暗示它默认设置为:#define PERL_USHORT_MAX ((unsigned short)~(unsigned)0)。如何从Perl端提取该值,我不知道 - 它基本上是通过按位否定短0得到的数字,所以如果无符号短是16字节,则PERL_USHORT_MAX将是16个,{{1将是15个,例如2 ^ 15-1,例如32767.

  • 此外,来自t/re/pat.t(正则表达式测试):PERL_SHORT_MAX(用于说明存储值中非默认编译的位置)。

所以,为了得到你的常数,你可以:

$::reg_infty   = $Config {reg_infty} // 32767;