diff options
author | Simon Marchi <simon.marchi@polymtl.ca> | 2021-07-13 11:31:42 -0400 |
---|---|---|
committer | Pedro Alves <pedro@palves.net> | 2021-07-15 15:10:52 +0100 |
commit | 67ea24cb99efcd50d8acb6ce3e3ffbd8c97f0829 (patch) | |
tree | 31dcd343217cede2087c7fb1b794ef7da81d9bd2 /gdb/ada-lang.c | |
parent | f9e5d80cf75c4c549c392b6bb1bd33e103824657 (diff) | |
download | binutils-67ea24cb99efcd50d8acb6ce3e3ffbd8c97f0829.zip binutils-67ea24cb99efcd50d8acb6ce3e3ffbd8c97f0829.tar.gz binutils-67ea24cb99efcd50d8acb6ce3e3ffbd8c97f0829.tar.bz2 |
gdb: consider null terminator for length arguments of value_cstring calls
This patch started when I looked at this bit in cli/cli-cmds.c:
if (*(char **) cmd->var)
return value_cstring (*(char **) cmd->var, strlen (*(char **) cmd->var),
builtin_type (gdbarch)->builtin_char);
else
return value_cstring ("", 1,
builtin_type (gdbarch)->builtin_char);
I found it odd that the first value_cstring call passes a length that
does not consider the null terminator of the C string, but second does.
I want to clarify the documentation of value_cstring and fix the one
that is wrong.
Debugging a little bit, I found that the first call is the wrong one.
Doing:
(gdb) set args foo
(gdb) print $_gdb_setting("args")
$1 = "foo"
creates a struct value of code TYPE_CODE_ARRAY of size 3, which doesn't
have a null terminator. That does not create a valid C string. It is
however printed correctly by GDB, because the printing code makes sure
not to read past the value's length.
A way to expose the bug is to print each element of the created string,
including the null terminator. Before:
(gdb) set args foo
(gdb) p $_gdb_setting("args")[3]
no such vector element
After:
(gdb) set args foo
(gdb) p $_gdb_setting("args")[3]
$1 = 0 '\000'
Another perhaps more convincing way of showing the bug is if the string
value is passed to an inferior function call;
(gdb) print an_inferior_function($_gdb_setting("args))
The space allocate for the string in the inferior will not take into
account a null terminator (with the string "foo", 3 bytes will be
allocated). If the inferior tries to read the string until the null
terminator, it will read past the allocated buffer. Compiling the
inferior with AddressSanitizer makes that bad access obvious.
I found a few calls to value_cstring that were wrong, I fixed them
all, all exercised by the test.
The change in guile/scm-math.c maybe requires a bit of explanation.
According to the doc of gdbscm_scm_to_string, if don't pass a length
pointer, we get back a null-terminated string. If we pass a length
pointer, we get a non-null-terminated string, but we get the length
separately. Trying to pass "len + 1" to value_cstring would lead to GDB
reading past the allocated buffer, that is exactly of length `len`. So
instead, don't pass a length pointer and use strlen on the result.
gdb.base/settings.exp and gdb.python/py-mi.exp required changes in some
expected outputs, because the array type created by $_gdb_setting_str
is now one element larger, to account for the null terminator. I don't
think this change in user-visible behavior is a problem.
Change-Id: If8dd13cce55c70521e34e7c360139064b4e87496
Diffstat (limited to 'gdb/ada-lang.c')
0 files changed, 0 insertions, 0 deletions