Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

basic_string<T>::push_back() crashes if sizeof(T)>sizeof(long long) #30802

Closed
karen-arutyunov mannequin opened this issue Dec 22, 2016 · 5 comments
Closed

basic_string<T>::push_back() crashes if sizeof(T)>sizeof(long long) #30802

karen-arutyunov mannequin opened this issue Dec 22, 2016 · 5 comments
Assignees
Labels
bugzilla Issues migrated from bugzilla libc++ libc++ C++ Standard Library. Not GNU libstdc++. Not libc++abi.

Comments

@karen-arutyunov
Copy link
Mannequin

karen-arutyunov mannequin commented Dec 22, 2016

Bugzilla Link 31454
Resolution FIXED
Resolved on Feb 07, 2018 13:30
Version 3.9
OS Linux
CC @hfinkel,@karen-arutyunov,@mclow

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 0002000 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)

@karen-arutyunov
Copy link
Mannequin Author

karen-arutyunov mannequin commented Dec 22, 2016

assigned to @mclow

@mclow
Copy link
Contributor

mclow commented Feb 14, 2017

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.

@mclow
Copy link
Contributor

mclow commented Feb 14, 2017

Turns out that's not the problem - but it's something we should do - when we're contemplating an ABI change (because it certainly would be).

BTW, you can reproduce this w/o a struct - basic_string<__uint128_t> does it also.

@mclow
Copy link
Contributor

mclow commented Feb 21, 2017

Changing __recommend() so that it never returns __min_cap makes the problem go away, but I don't understand why.

size_type __recommend(size_type __s) _NOEXCEPT
    {
    if (__s < __min_cap) return static_cast<size_type>(__min_cap) - 1;
    size_type __guess = __align_it<sizeof(value_type) < __alignment ?
                 __alignment/sizeof(value_type) : 1 > (__s+1) - 1;
    if (__guess == __min_cap) ++__guess;
    return __guess;
    }

More investigation coming, but if you need a quick fix...

@mclow
Copy link
Contributor

mclow commented Feb 7, 2018

revision 324531 fixes this.

@llvmbot llvmbot transferred this issue from llvm/llvm-bugzilla-archive Dec 10, 2021
This issue was closed.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bugzilla Issues migrated from bugzilla libc++ libc++ C++ Standard Library. Not GNU libstdc++. Not libc++abi.
Projects
None yet
Development

No branches or pull requests

1 participant