Bug 14303 – rt.util.container.array.Array unittest contains invalid code

Status
RESOLVED
Resolution
FIXED
Severity
critical
Priority
P1
Component
druntime
Product
D
Version
D2
Platform
All
OS
All
Creation time
2015-03-18T06:07:00Z
Last change time
2017-07-19T17:41:16Z
Assigned to
nobody
Creator
braddr

Comments

Comment #0 by braddr — 2015-03-18T06:07:59Z
The last block of unit tests: unittest { alias RC = common.RC; Array!RC ary; size_t cnt; assert(cnt == 0); ary.insertBack(RC(&cnt)); assert(cnt == 1); ary.insertBack(ary.front); // <--- assert(cnt == 2); ary.popBack(); assert(cnt == 1); ary.popBack(); assert(cnt == 0); } The marked line takes the front element of array and passes it by reference to ary.insertBack. The problem is that insertBack can realloc the array which can cause it to be moved, invalidating the reference. I'm seeing this happen and resulting in a segfault. For evidence of the problem, changing Array.insertBack to: void insertBack()(auto ref T val) { static if (is(T == common.RC)) printf("val._cnt: %p\n", val._cnt); .fflush(.stdout); length = length + 1; static if (is(T == common.RC)) printf("val._cnt: %p\n", val._cnt); .fflush(.stdout); back = val; } val._cnt: 00000000001AF960 (matches &cnt) val._cnt: 00000000001A003C (doesn't match) Adding more printf's to clarify the flow between those two points: Array.length _ptr before xrealloc: 0000000000312900 Array.length _ptr after xrealloc: 0000000000312A60 RC.length grow common.initialize &t: 0000000000312A70, t._cnt: 0000000000000000 common.initialize memset Not sure what caused the old _cnt pointer to get overwritten with a new value, but it obviously was, thankfully exposing the problem. The code certainly _looks_ innocent enough. It took way more digging than it should have for me to realize what the problem is. I hate to just remove the test case though. Maybe replace: ary.insertBack(ary.front); with: ary.insertBack(RC(&cnt)); assert(cnt == 2); ary.back = ary.front; assert(cnt == 2);
Comment #1 by github-bugzilla — 2015-03-18T08:03:10Z
Commits pushed to master at https://github.com/D-Programming-Language/druntime https://github.com/D-Programming-Language/druntime/commit/ebe07a3f34518e4bbde410f61572b468ac7e8f4e fix issue 14303 rt.util.container.array.Array has invalid unittest replace invalid test with something similar but valid https://github.com/D-Programming-Language/druntime/commit/c41cb051c8188bdfc5a024a266d11e4f7b2d5837 Merge pull request #1192 from braddr/fix-array-unittest fix issue 14303 rt.util.container.array.Array has invalid unittest
Comment #2 by github-bugzilla — 2015-06-17T21:02:14Z
Comment #3 by github-bugzilla — 2017-07-19T17:41:16Z
Commits pushed to dmd-cxx at https://github.com/dlang/druntime https://github.com/dlang/druntime/commit/ebe07a3f34518e4bbde410f61572b468ac7e8f4e fix issue 14303 rt.util.container.array.Array has invalid unittest https://github.com/dlang/druntime/commit/c41cb051c8188bdfc5a024a266d11e4f7b2d5837 Merge pull request #1192 from braddr/fix-array-unittest