You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
In build2 toolchain project we instantiate basic_string template with a char-like struct. Pushing back objects for such a string cases a program crash inside libc’s free() function.
The following code example reproduces the issue. In a real-life code such a char type requires a proper specialization of the char_traits template but for the current problem this is irrelevant.
The problem relates to the fact that after __set_long_cap(3) was called (inside the 2nd push_back()) the subsequent __get_long_cap() call (inside the 3rd push_back()) returns 2. After that (inside the 3rd push_back()) the expression (__sz == __cap) evaluates to false (as __sz == 2 and __cap == 1), this why __grow_by() is not called, and so traits_type::assign(*++__p, value_type()) writes out of the allocated memory block.
test.cxx:
#include
struct bc
{
long long a;
char b; // If to remove this member the issue disappears.
};
typedef std::basic_string bstring;
int
main ()
{
bc c;
bstring s;
s.push_back (c);
s.push_back (c);
s.push_back (c);
}
I've done some investigation here. The problem is that the arithmetic here for large "character type" is incorrect. For this example, there should be no short strings, except for the empty string - but libc++ gets this wrong.
There's also the case for even larger "character types" where there are no short strings at all, which we don't handle either.
The problem is in the calculation for __min_cap, where it assumes that we'll always have room for at least two value of type CharT.
Extended Description
In build2 toolchain project we instantiate basic_string template with a char-like struct. Pushing back objects for such a string cases a program crash inside libc’s free() function.
The following code example reproduces the issue. In a real-life code such a char type requires a proper specialization of the char_traits template but for the current problem this is irrelevant.
The problem relates to the fact that after __set_long_cap(3) was called (inside the 2nd push_back()) the subsequent __get_long_cap() call (inside the 3rd push_back()) returns 2. After that (inside the 3rd push_back()) the expression (__sz == __cap) evaluates to false (as __sz == 2 and __cap == 1), this why __grow_by() is not called, and so traits_type::assign(*++__p, value_type()) writes out of the allocated memory block.
test.cxx:
#include
struct bc
{
long long a;
char b; // If to remove this member the issue disappears.
};
typedef std::basic_string bstring;
int
main ()
{
bc c;
bstring s;
s.push_back (c);
s.push_back (c);
s.push_back (c);
}
$ clang++ -stdlib=libc++ test.cxx
$ ./a.out
*** Error in `./a.out': free(): invalid next size (fast): 0x0000000000809010 ***
======= Backtrace: =========
/lib64/libc.so.6(+0x77d75)[0x7f7603aafd75]
/lib64/libc.so.6(+0x801ca)[0x7f7603ab81ca]
/lib64/libc.so.6(cfree+0x4c)[0x7f7603abb72c]
./a.out[0x401134]
./a.out[0x400cb3]
/lib64/libc.so.6(__libc_start_main+0xf0)[0x7f7603a58580]
./a.out[0x400ab9]
======= Memory map: ========
00400000-00402000 r-xp 00000000 fd:00 33893461 /home/karen/projects/build2/a.out
00601000-00602000 r--p 00001000 fd:00 33893461 /home/karen/projects/build2/a.out
00602000-00603000 rw-p 00002000 fd:00 33893461 /home/karen/projects/build2/a.out
00809000-0082a000 rw-p 00000000 00:00 0 [heap]
7f75fc000000-7f75fc021000 rw-p 00000000 00:00 0
7f75fc021000-7f7600000000 ---p 00000000 00:00 0
7f7603612000-7f7603619000 r-xp 00000000 fd:00 34797155 /usr/lib64/librt-2.22.so
7f7603619000-7f7603818000 ---p 00007000 fd:00 34797155 /usr/lib64/librt-2.22.so
7f7603818000-7f7603819000 r--p 00006000 fd:00 34797155 /usr/lib64/librt-2.22.so
7f7603819000-7f760381a000 rw-p 00007000 fd:00 34797155 /usr/lib64/librt-2.22.so
7f760381a000-7f7603832000 r-xp 00000000 fd:00 33555771 /usr/lib64/libpthread-2.22.so
7f7603832000-7f7603a31000 ---p 00018000 fd:00 33555771 /usr/lib64/libpthread-2.22.so
7f7603a31000-7f7603a33000 r--p 00017000 fd:00 33555771 /usr/lib64/libpthread-2.22.so
7f7603a33000-7f7603a34000 rw-p 00019000 fd:00 33555771 /usr/lib64/libpthread-2.22.so
7f7603a34000-7f7603a38000 rw-p 00000000 00:00 0
7f7603a38000-7f7603bef000 r-xp 00000000 fd:00 33555743 /usr/lib64/libc-2.22.so
7f7603bef000-7f7603def000 ---p 001b7000 fd:00 33555743 /usr/lib64/libc-2.22.so
7f7603def000-7f7603df3000 r--p 001b7000 fd:00 33555743 /usr/lib64/libc-2.22.so
7f7603df3000-7f7603df5000 rw-p 001bb000 fd:00 33555743 /usr/lib64/libc-2.22.so
7f7603df5000-7f7603df9000 rw-p 00000000 00:00 0
7f7603df9000-7f7603e0f000 r-xp 00000000 fd:00 35543539 /usr/lib64/libgcc_s-5.3.1-20160406.so.1
7f7603e0f000-7f760400e000 ---p 00016000 fd:00 35543539 /usr/lib64/libgcc_s-5.3.1-20160406.so.1
7f760400e000-7f760400f000 r--p 00015000 fd:00 35543539 /usr/lib64/libgcc_s-5.3.1-20160406.so.1
7f760400f000-7f7604010000 rw-p 00016000 fd:00 35543539 /usr/lib64/libgcc_s-5.3.1-20160406.so.1
7f7604010000-7f7604111000 r-xp 00000000 fd:00 34797143 /usr/lib64/libm-2.22.so
7f7604111000-7f7604310000 ---p 00101000 fd:00 34797143 /usr/lib64/libm-2.22.so
7f7604310000-7f7604311000 r--p 00100000 fd:00 34797143 /usr/lib64/libm-2.22.so
7f7604311000-7f7604312000 rw-p 00101000 fd:00 34797143 /usr/lib64/libm-2.22.so
7f7604312000-7f7604357000 r-xp 00000000 fd:00 35206817 /usr/local/lib/libc++abi.so.1.0
7f7604357000-7f7604556000 ---p 00045000 fd:00 35206817 /usr/local/lib/libc++abi.so.1.0
7f7604556000-7f7604559000 r--p 00044000 fd:00 35206817 /usr/local/lib/libc++abi.so.1.0
7f7604559000-7f760455a000 rw-p 00047000 fd:00 35206817 /usr/local/lib/libc++abi.so.1.0
7f760455a000-7f760460c000 r-xp 00000000 fd:00 34909176 /usr/local/lib/libc++.so.1.0
7f760460c000-7f760480b000 ---p 000b2000 fd:00 34909176 /usr/local/lib/libc++.so.1.0
7f760480b000-7f7604810000 r--p 000b1000 fd:00 34909176 /usr/local/lib/libc++.so.1.0
7f7604810000-7f7604811000 rw-p 000b6000 fd:00 34909176 /usr/local/lib/libc++.so.1.0
7f7604811000-7f7604814000 rw-p 00000000 00:00 0
7f7604814000-7f7604835000 r-xp 00000000 fd:00 33555725 /usr/lib64/ld-2.22.so
7f7604a1b000-7f7604a20000 rw-p 00000000 00:00 0
7f7604a31000-7f7604a34000 rw-p 00000000 00:00 0
7f7604a34000-7f7604a35000 r--p 00020000 fd:00 33555725 /usr/lib64/ld-2.22.so
7f7604a35000-7f7604a36000 rw-p 00021000 fd:00 33555725 /usr/lib64/ld-2.22.so
7f7604a36000-7f7604a37000 rw-p 00000000 00:00 0
7ffc3d4e9000-7ffc3d50a000 rw-p 00000000 00:00 0 [stack]
7ffc3d5c3000-7ffc3d5c5000 r--p 00000000 00:00 0 [vvar]
7ffc3d5c5000-7ffc3d5c7000 r-xp 00000000 00:00 0 [vdso]
ffffffffff600000-ffffffffff601000 r-xp 00000000 00:00 0 [vsyscall]
Aborted (core dumped)
The text was updated successfully, but these errors were encountered: