www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.bugs - [Issue 18692] New: assignment of std.regex.Captures reads freed

https://issues.dlang.org/show_bug.cgi?id=18692

          Issue ID: 18692
           Summary: assignment of std.regex.Captures reads freed memory
                    from 2.072.0 to 2.078.3 inclusive
           Product: D
           Version: D2
          Hardware: x86_64
                OS: Linux
            Status: NEW
          Severity: regression
          Priority: P1
         Component: phobos
          Assignee: nobody puremagic.com
          Reporter: martin.dorey hitachivantara.com

When I was working on:

Issue 18691: assigning a std.regex.Captures with 3 or more groups causes double
free

... I couldn't understand how this change:

https://github.com/dlang/phobos/commit/872673d5570f1ee79df4b9e47d8f3d2cf4e49536

... the "Use ref-counting for Captures struct" from  DmitryOlshansky, could be
right.  How can he get away with having the _refcount that applies to
big_matches not stored in an object with the same lifetime as big_matches?  I
have about two days' familiarity with D, so I assume I'm missing something. 
That said, here's a program that goes wrong with the first release of dmd that
included that change.  First, it working on the preceding version.

martind swiftboat:~/tmp/D134366$ cat two_years.d
import std.regex;

void main() {
    auto rx = regex("()()()");
    auto ma = "".matchFirst(rx);
    auto ma2 = ma;
    ma = ma2;
    ma[1];
}
martind swiftboat:~/tmp/D134366$ dmd --version
DMD64 D Compiler v2.071.0
Copyright (c) 1999-2015 by Digital Mars written by Walter Bright
martind swiftboat:~/tmp/D134366$ dmd two_years.d && MALLOC_PERTURB_=1
./two_years 
martind swiftboat:~/tmp/D134366$ 

2.072.0 was afflicted by
https://digitalmars.com/d/archives/digitalmars/D/dmd_or_phobos_were_broken_in_ubuntu_16.10_d-apt_294148.html,
hence the extra shared library parameters, which make no difference on 2.071.0.

martind balance:~/tmp/D134366$ dmd --version
DMD64 D Compiler v2.072.0
Copyright (c) 1999-2016 by Digital Mars written by Walter Bright
martind balance:~/tmp/D134366$ dmd -defaultlib=libphobos2.so -fPIC two_years.d
&& MALLOC_PERTURB_=1 ./two_years 
core.exception.RangeError std/regex/package.d(565): Range violation
----------------
??:? _d_arraybounds [0xf693d091]
??:? std.regex.__array [0xf68f6f1e]
??:? std.regex.Captures!(immutable(char)[],
ulong).Captures.opIndex!().opIndexinout(pure nothrow  trusted
inout(immutable(char)[]) function(ulong)) [0xb4f37081]
??:? _Dmain [0xb4f0f60f]
??:? _D2rt6dmain211_d_run_mainUiPPaPUAAaZiZ6runAllMFZ9__lambda1MFZv
[0xf696d68f]
??:? void rt.dmain2._d_run_main(int, char**, extern (C) int
function(char[][])*).tryExec(scope void delegate()) [0xf696d5bb]
??:? void rt.dmain2._d_run_main(int, char**, extern (C) int
function(char[][])*).runAll() [0xf696d634]
??:? void rt.dmain2._d_run_main(int, char**, extern (C) int
function(char[][])*).tryExec(scope void delegate()) [0xf696d5bb]
??:? _d_run_main [0xf696d51f]
??:? main [0xb4f3a67f]
??:? __libc_start_main [0xf55f52b0]
martind balance:~/tmp/D134366$ 

valgrind is unhappy too and more verbosely, making it explicit that the problem
is reading from freed memory.  The problems continue up to and including
2.078.3 but disappear for 2.079.0 and are absent in master.  I suspect that the
 MartinNowak change I finger in Issue 18691 fixed this particular reference
counting issue at the expense of introducing that one.

--
Mar 28 2018