Bug 89629 - std::hash<std::string> segfault for long strings
Summary: std::hash<std::string> segfault for long strings
Status: RESOLVED FIXED
Alias: None
Product: gcc
Classification: Unclassified
Component: libstdc++ (show other bugs)
Version: 8.3.0
: P3 normal
Target Milestone: 7.5
Assignee: Not yet assigned to anyone
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2019-03-07 18:50 UTC by Dan Stahlke
Modified: 2019-05-08 12:20 UTC (History)
1 user (show)

See Also:
Host:
Target:
Build:
Known to work:
Known to fail:
Last reconfirmed: 2019-03-08 00:00:00


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Dan Stahlke 2019-03-07 18:50:07 UTC
_Hash_bytes crashes when len is 2^31 or greater.  The length is converted to int at hash_bytes.cc line 142, resulting in a negative number if the length doesn't fit in an int variable.  Then end < buf resulting in an infinite loop that eventually runs into inaccessible memory.

#include <unordered_set>
#include <string>
#include <iostream>

int main() {
    size_t big = size_t(1) << 31;
    std::cout << "line " << __LINE__ << std::endl;
    // this succeeds
    std::hash<std::string>{}(std::string(big - 1, 'a'));
    std::cout << "line " << __LINE__ << std::endl;
    // segfault at libstdc++-v3/libsupc++/hash_bytes.cc:147
    std::hash<std::string>{}(std::string(big, 'a'));
    std::cout << "line " << __LINE__ << std::endl;
}
Comment 1 Jonathan Wakely 2019-03-08 22:33:04 UTC
I think we should just use size_t for the len_aligned variable:

--- a/libstdc++-v3/libsupc++/hash_bytes.cc
+++ b/libstdc++-v3/libsupc++/hash_bytes.cc
@@ -139,7 +139,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 
     // Remove the bytes not divisible by the sizeof(size_t).  This
     // allows the main loop to process the data as 64-bit integers.
-    const int len_aligned = len & ~0x7;
+    const size_t len_aligned = len & ~0x7;
     const char* const end = buf + len_aligned;
     size_t hash = seed ^ (len * mul);
     for (const char* p = buf; p != end; p += 8)
Comment 2 Jonathan Wakely 2019-03-11 13:46:40 UTC
Author: redi
Date: Mon Mar 11 13:46:05 2019
New Revision: 269584

URL: https://gcc.gnu.org/viewcvs?rev=269584&root=gcc&view=rev
Log:
PR libstdc++/89629 fix _Hash_bytes for lengths > INT_MAX

	PR libstdc++/89629
	* libsupc++/hash_bytes.cc [__SIZEOF_SIZE_T__ == 8] (_Hash_bytes):
	Use correct type for len_aligned.
	* testsuite/20_util/hash/89629.cc: New test.

Added:
    trunk/libstdc++-v3/testsuite/20_util/hash/89629.cc
Modified:
    trunk/libstdc++-v3/ChangeLog
    trunk/libstdc++-v3/libsupc++/hash_bytes.cc
Comment 3 Jonathan Wakely 2019-03-11 14:21:30 UTC
Fixed on trunk so far.
Comment 4 Jonathan Wakely 2019-05-07 15:46:31 UTC
Author: redi
Date: Tue May  7 15:45:59 2019
New Revision: 270959

URL: https://gcc.gnu.org/viewcvs?rev=270959&root=gcc&view=rev
Log:
PR libstdc++/89629 fix _Hash_bytes for lengths > INT_MAX

Backport from mainline
2019-03-11  Jonathan Wakely  <jwakely@redhat.com>

	PR libstdc++/89629
	* libsupc++/hash_bytes.cc [__SIZEOF_SIZE_T__ == 8] (_Hash_bytes):
	Use correct type for len_aligned.
	* testsuite/20_util/hash/89629.cc: New test.

Added:
    branches/gcc-8-branch/libstdc++-v3/testsuite/20_util/hash/89629.cc
Modified:
    branches/gcc-8-branch/libstdc++-v3/ChangeLog
    branches/gcc-8-branch/libstdc++-v3/libsupc++/hash_bytes.cc
Comment 5 Jonathan Wakely 2019-05-08 12:17:51 UTC
Author: redi
Date: Wed May  8 12:17:20 2019
New Revision: 271009

URL: https://gcc.gnu.org/viewcvs?rev=271009&root=gcc&view=rev
Log:
PR libstdc++/89629 fix _Hash_bytes for lengths > INT_MAX

Backport from mainline
2019-03-11  Jonathan Wakely  <jwakely@redhat.com>

	PR libstdc++/89629
	* libsupc++/hash_bytes.cc [__SIZEOF_SIZE_T__ == 8] (_Hash_bytes):
	Use correct type for len_aligned.
	* testsuite/20_util/hash/89629.cc: New test.

Added:
    branches/gcc-7-branch/libstdc++-v3/testsuite/20_util/hash/89629.cc
Modified:
    branches/gcc-7-branch/libstdc++-v3/ChangeLog
    branches/gcc-7-branch/libstdc++-v3/libsupc++/hash_bytes.cc
Comment 6 Jonathan Wakely 2019-05-08 12:20:47 UTC
Fixed in 9.1, and will be fixed in 8.4 and 7.5 when they get released.