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: nob...@puremagic.com
          Reporter: martin.do...@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.

--

Reply via email to