develooper Front page | perl.perl5.porters | Postings from September 2013

[perl #120041] regcomp.c missing parens and broken STCLASS

Thread Previous | Thread Next
From:
l . mai @ web . de
Date:
September 28, 2013 21:59
Subject:
[perl #120041] regcomp.c missing parens and broken STCLASS
Message ID:
rt-3.6.HEAD-31239-1380405563-615.120041-75-0@perl.org
# New Ticket Created by  l.mai@web.de 
# Please include the string:  [perl #120041]
# in the subject line of all future correspondence about this issue. 
# <URL: https://rt.perl.org:443/rt3/Ticket/Display.html?id=120041 >



This is a bug report for perl from l.mai@web.de,
generated with the help of perlbug 1.39 running under perl 5.18.1.


-----------------------------------------------------------------
[Please describe your issue here]

This bug report is about regcomp.c in blead
(6d76e7fc723ef1780fb1cb21c20437473219e384).

Commit a0dd42312a1f26356d2fdf49656e45b77c2cefb5 changed a struct field to a
bit. The corresponding tests turned from cBOOL((node)->next_off) to
ANYOF_FLAGS(ssc) & ANYOF_EMPTY_STRING.

However, gcc complains about three lines in regcomp.c because they're missing
parens: ! x & y instead of !(x & y).
(warning: suggest parentheses around operand of '!' or change '&' to '&&' or '!' to '~' [-Wparentheses])


line 838:
if (! ANYOF_FLAGS(ssc) & ANYOF_EMPTY_STRING) {

line 6614:
        if ((!(r->anchored_substr || r->anchored_utf8) || r->anchored_offset)
            && stclass_flag
            && ! ANYOF_FLAGS(data.start_class) & ANYOF_EMPTY_STRING
            && !ssc_is_anything(data.start_class))

line 6690:
        if (! ANYOF_FLAGS(data.start_class) & ANYOF_EMPTY_STRING
            && !ssc_is_anything(data.start_class))


As it is, these conditions can never be true because ! ANYOF_FLAGS(...) is
either 0 or 1. ANYOF_EMPTY_STRING is 4. 0 & 4 is 0; 1 & 4 is 0.


I tried to fix the code by adding parens. This makes the following code fail:

% ./perl -we '"" =~ /^A*\z/ or die;'
Died at -e line 1.

I took a closer look at line 838. It's part of this function:

STATIC int
S_ssc_is_anything(pTHX_ const regnode_ssc *ssc)
{
    /* Returns TRUE if the SSC 'ssc' can match the empty string or any code
     * point */

    UV start, end;
    bool ret;

    PERL_ARGS_ASSERT_SSC_IS_ANYTHING;

    assert(OP(ssc) == ANYOF_SYNTHETIC);

    if (!(ANYOF_FLAGS(ssc) & ANYOF_EMPTY_STRING)) {
        return FALSE;
    }

    ...
}

This logic looks reversed to me: If S_ssc_is_anything is supposed to return
TRUE if the empty string or any char is allowed, then the function shouldn't
immediately return FALSE if the flags don't allow an empty string. Instead I'd
expect something like this:

    if (ANYOF_FLAGS(ssc) & ANYOF_EMPTY_STRING) {
        return TRUE;
    }

This change would make the separate !(ANYOF_FLAGS(data.start_class) &
ANYOF_EMPTY_STRING) checks in lines 6614 and 6690 redundant.


However, it doesn't fix the match failure. (But perl -Mre=debug somehow does.)

With './perl -Dr -we '"" =~ /^A*\z/ or die;' I can see this bit:
floating ""$ at 0..2147483647 (checking floating) stclass ANYOF_SYNTHETIC[A] anchored(BOL) minlen 0

I'm pretty sure the ANYOF_SYNTHETIC[A] shouldn't be there but I don't really
understand the regex code.


Conclusion: The existing bit testing code is wrong and gcc's warnings are
right. But by always failing it apparently hides another bug in the stclass
optimization.

[Please do not change anything below this line]
-----------------------------------------------------------------
---
Flags:
    category=core
    severity=medium
---
This perlbug was built using Perl 5.12.1 - Thu Jun  3 20:09:15 CEST 2010
It is being executed now by  Perl 5.18.1 - Tue Aug 13 07:08:47 CEST 2013.

Site configuration information for perl 5.18.1:

Configured by mauke at Tue Aug 13 07:08:47 CEST 2013.

Summary of my perl5 (revision 5 version 18 subversion 1) configuration:
   
  Platform:
    osname=linux, osvers=3.5.7-gentoo, archname=i686-linux
    uname='linux nora 3.5.7-gentoo #5 preempt sat jan 26 16:46:10 cet 2013 i686 amd athlon(tm) 64 processor 3200+ authenticamd gnulinux '
    config_args=''
    hint=recommended, useposix=true, d_sigaction=define
    useithreads=undef, usemultiplicity=undef
    useperlio=define, d_sfio=undef, uselargefiles=define, usesocks=undef
    use64bitint=undef, use64bitall=undef, uselongdouble=undef
    usemymalloc=n, bincompat5005=undef
  Compiler:
    cc='cc', ccflags ='-fno-strict-aliasing -pipe -fstack-protector -I/usr/local/include -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64',
    optimize='-O2 -flto',
    cppflags='-fno-strict-aliasing -pipe -fstack-protector -I/usr/local/include'
    ccversion='', gccversion='4.8.1', gccosandvers=''
    intsize=4, longsize=4, ptrsize=4, doublesize=8, byteorder=1234
    d_longlong=define, longlongsize=8, d_longdbl=define, longdblsize=12
    ivtype='long', ivsize=4, nvtype='double', nvsize=8, Off_t='off_t', lseeksize=8
    alignbytes=4, prototype=define
  Linker and Libraries:
    ld='cc', ldflags ='-O2 -flto -fstack-protector -L/usr/local/lib'
    libpth=/usr/local/lib /lib/../lib /usr/lib/../lib /lib /usr/lib
    libs=-lnsl -lgdbm -ldb -ldl -lm -lcrypt -lutil -lc -lgdbm_compat
    perllibs=-lnsl -ldl -lm -lcrypt -lutil -lc
    libc=/lib/libc-2.15.so, so=so, useshrplib=false, libperl=libperl.a
    gnulibc_version='2.15'
  Dynamic Linking:
    dlsrc=dl_dlopen.xs, dlext=so, d_dlsymun=undef, ccdlflags='-Wl,-E'
    cccdlflags='-fPIC', lddlflags='-shared -O2 -flto -L/usr/local/lib -fstack-protector'

Locally applied patches:
    SAVEARGV0 - disable magic open in <ARGV>

---
@INC for perl 5.18.1:
    /home/mauke/usr/local/lib/perl5/site_perl/5.18.1/i686-linux
    /home/mauke/usr/local/lib/perl5/site_perl/5.18.1
    /home/mauke/usr/local/lib/perl5/5.18.1/i686-linux
    /home/mauke/usr/local/lib/perl5/5.18.1
    .

---
Environment for perl 5.18.1:
    HOME=/home/mauke
    LANG=en_US.UTF-8
    LANGUAGE (unset)
    LC_COLLATE=POSIX
    LD_LIBRARY_PATH=/home/mauke/usr/local/lib
    LOGDIR (unset)
    PATH=/home/mauke/usr/perlbrew/bin:/home/mauke/usr/local/bin:/usr/local/bin:/usr/bin:/bin:/opt/bin:/usr/i686-pc-linux-gnu/gcc-bin/4.6.3:/opt/sun-jdk-1.4.2.13/bin:/opt/sun-jdk-1.4.2.13/jre/bin:/opt/sun-jdk-1.4.2.13/jre/javaws:/opt/dmd/bin:/usr/games/bin
    PERLBREW_BASHRC_VERSION=0.43
    PERLBREW_HOME=/home/mauke/.perlbrew
    PERLBREW_PATH=/home/mauke/usr/perlbrew/bin
    PERLBREW_ROOT=/home/mauke/usr/perlbrew
    PERLBREW_VERSION=0.27
    PERL_BADLANG (unset)
    PERL_UNICODE=SAL
    SHELL=/bin/bash


Thread Previous | Thread Next


nntp.perl.org: Perl Programming lists via nntp and http.
Comments to Ask Bjørn Hansen at ask@perl.org | Group listing | About