diff options
author | Bernd Edlinger <bernd.edlinger@hotmail.de> | 2018-08-29 22:16:09 +0000 |
---|---|---|
committer | Jeff Law <law@gcc.gnu.org> | 2018-08-29 16:16:09 -0600 |
commit | 1ebf0641a5201939cbaa1cc4f008bb8eda68895c (patch) | |
tree | db468a623870c89e111e941c934472e18869fe46 /gcc | |
parent | d66ab7d12bb632c3de947f535d189275209a3915 (diff) | |
download | gcc-1ebf0641a5201939cbaa1cc4f008bb8eda68895c.zip gcc-1ebf0641a5201939cbaa1cc4f008bb8eda68895c.tar.gz gcc-1ebf0641a5201939cbaa1cc4f008bb8eda68895c.tar.bz2 |
re PR middle-end/87053 (wrong code with c_strlen)
gcc:
2018-08-22 Bernd Edlinger <bernd.edlinger@hotmail.de>
PR middle-end/87053
* builtins.c (c_strlen): Improve range checks.
testsuite:
2018-08-22 Bernd Edlinger <bernd.edlinger@hotmail.de>
PR middle-end/87053
* gcc.c-torture/execute/pr87053.c: New test.
From-SVN: r263968
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/ChangeLog | 5 | ||||
-rw-r--r-- | gcc/builtins.c | 11 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 5 | ||||
-rw-r--r-- | gcc/testsuite/gcc.c-torture/execute/pr87053.c | 17 |
4 files changed, 35 insertions, 3 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 3cf10ca..8865f31 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,8 @@ +2018-08-29 Bernd Edlinger <bernd.edlinger@hotmail.de> + + PR middle-end/87053 + * builtins.c (c_strlen): Improve range checks. + 2018-08-29 Martin Sebor <msebor@redhat.com> Jeff Law <law@redhat.com> diff --git a/gcc/builtins.c b/gcc/builtins.c index c9de1e6..58ea747 100644 --- a/gcc/builtins.c +++ b/gcc/builtins.c @@ -567,7 +567,7 @@ string_length (const void *ptr, unsigned eltsize, unsigned maxelts) tree c_strlen (tree src, int only_value, unsigned eltsize) { - gcc_assert (eltsize == 1 || eltsize == 2 || eltsize == 4); + gcc_checking_assert (eltsize == 1 || eltsize == 2 || eltsize == 4); STRIP_NOPS (src); if (TREE_CODE (src) == COND_EXPR && (only_value || !TREE_SIDE_EFFECTS (TREE_OPERAND (src, 0)))) @@ -656,10 +656,10 @@ c_strlen (tree src, int only_value, unsigned eltsize) a null character if we can represent it as a single HOST_WIDE_INT. */ if (byteoff == 0) eltoff = 0; - else if (! tree_fits_shwi_p (byteoff)) + else if (! tree_fits_uhwi_p (byteoff) || tree_to_uhwi (byteoff) % eltsize) eltoff = -1; else - eltoff = tree_to_shwi (byteoff) / eltsize; + eltoff = tree_to_uhwi (byteoff) / eltsize; /* If the offset is known to be out of bounds, warn, and call strlen at runtime. */ @@ -691,6 +691,11 @@ c_strlen (tree src, int only_value, unsigned eltsize) unsigned len = string_length (ptr + eltoff * eltsize, eltsize, strelts - eltoff); + /* Don't know what to return if there was no zero termination. + Ideally this would turn into a gcc_checking_assert over time. */ + if (len > maxelts - eltoff) + return NULL_TREE; + return ssize_int (len); } diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index e38dab2..317cb47 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2018-08-29 Bernd Edlinger <bernd.edlinger@hotmail.de> + + PR middle-end/87053 + * gcc.c-torture/execute/pr87053.c: New test. + 2018-08-29 Jakub Jelinek <jakub@redhat.com> PR c++/87095 diff --git a/gcc/testsuite/gcc.c-torture/execute/pr87053.c b/gcc/testsuite/gcc.c-torture/execute/pr87053.c new file mode 100644 index 0000000..0170731 --- /dev/null +++ b/gcc/testsuite/gcc.c-torture/execute/pr87053.c @@ -0,0 +1,17 @@ +/* PR middle-end/87053 */ + +const union +{ struct { + char x[4]; + char y[4]; + }; + struct { + char z[8]; + }; +} u = {{"1234", "567"}}; + +int main () +{ + if (__builtin_strlen (u.z) != 7) + __builtin_abort (); +} |