From 39086a0e1346572fac07542ede2a1ef153308a2a Mon Sep 17 00:00:00 2001 From: Pedro Alves Date: Mon, 11 Mar 2013 12:22:20 +0000 Subject: [PATCH] Avoid invalid pointer to pointer conversions. Casts between 'char **' <-> 'unsigned char **' and 'char **' <-> const char **' are actually invalid: http://gcc.gnu.org/ml/gcc-help/2013-03/msg00118.html In a nutshell, char (and variants) can alias anything, but pointers to chars get no special treatment (cf. C99/N1256, 6.5/7). Turns out older gcc's actually warn/complain on these constructs, though newer one's don't: http://sourceware.org/ml/gdb-patches/2013-03/msg00429.html http://sourceware.org/ml/gdb-patches/2013-03/msg00430.html This patch fixes the cases I added last week. It also fixes one other preexisting case in charset.c, though it seems even older gccs don't complain of char * <-> const char * aliasing. Tested on x86_64 Fedora 17. gdb/ 2013-03-11 Pedro Alves * charset.c (convert_between_encodings): Don't cast between different pointer to pointer types. Instead, make the 'inp' local be of the type iconv expects. (wchar_iterate): Don't cast between different pointer to pointer types. Instead, use new pointer local of the type iconv expects. * target.c (target_read_stralloc, target_fileio_read_stralloc): Add new local of type char pointer, and use it to get a char/string view of the byte buffer, instead of casting between pointer to pointer types. --- gdb/ChangeLog | 12 ++++++++++++ gdb/charset.c | 13 +++++++------ gdb/target.c | 30 ++++++++++++++++-------------- 3 files changed, 35 insertions(+), 20 deletions(-) diff --git a/gdb/ChangeLog b/gdb/ChangeLog index 0993c7454ed..3334f622f66 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,3 +1,15 @@ +2013-03-11 Pedro Alves + + * charset.c (convert_between_encodings): Don't cast between + different pointer to pointer types. Instead, make the 'inp' local + be of the type iconv expects. + (wchar_iterate): Don't cast between different pointer to pointer + types. Instead, use new pointer local of the type iconv expects. + * target.c (target_read_stralloc, target_fileio_read_stralloc): + Add new local of type char pointer, and use it to get a + char/string view of the byte buffer, instead of casting between + pointer to pointer types. + 2013-03-11 Hafiz Abid Qadeer * remote.c (remote_set_trace_buffer_size): Move != operator diff --git a/gdb/charset.c b/gdb/charset.c index 4cd6f205a7d..5835fd40872 100644 --- a/gdb/charset.c +++ b/gdb/charset.c @@ -474,7 +474,7 @@ convert_between_encodings (const char *from, const char *to, iconv_t desc; struct cleanup *cleanups; size_t inleft; - char *inp; + ICONV_CONST char *inp; unsigned int space_request; /* Often, the host and target charsets will be the same. */ @@ -490,7 +490,7 @@ convert_between_encodings (const char *from, const char *to, cleanups = make_cleanup (cleanup_iconv, &desc); inleft = num_bytes; - inp = (char *) bytes; + inp = (ICONV_CONST char *) bytes; space_request = num_bytes; @@ -506,7 +506,7 @@ convert_between_encodings (const char *from, const char *to, outp = obstack_base (output) + old_size; outleft = space_request; - r = iconv (desc, (ICONV_CONST char **) &inp, &inleft, &outp, &outleft); + r = iconv (desc, &inp, &inleft, &outp, &outleft); /* Now make sure that the object on the obstack only includes bytes we have converted. */ @@ -640,14 +640,15 @@ wchar_iterate (struct wchar_iterator *iter, out_request = 1; while (iter->bytes > 0) { + ICONV_CONST char *inptr = (ICONV_CONST char *) iter->input; char *outptr = (char *) &iter->out[0]; const gdb_byte *orig_inptr = iter->input; size_t orig_in = iter->bytes; size_t out_avail = out_request * sizeof (gdb_wchar_t); size_t num; - size_t r = iconv (iter->desc, - (ICONV_CONST char **) &iter->input, - &iter->bytes, &outptr, &out_avail); + size_t r = iconv (iter->desc, &inptr, &iter->bytes, &outptr, &out_avail); + + iter->input = (gdb_byte *) inptr; if (r == (size_t) -1) { diff --git a/gdb/target.c b/gdb/target.c index 0329da32adf..a961d7b831e 100644 --- a/gdb/target.c +++ b/gdb/target.c @@ -2378,11 +2378,12 @@ char * target_read_stralloc (struct target_ops *ops, enum target_object object, const char *annex) { - char *buffer; + gdb_byte *buffer; + char *bufstr; LONGEST i, transferred; - transferred = target_read_alloc_1 (ops, object, annex, - (gdb_byte **) &buffer, 1); + transferred = target_read_alloc_1 (ops, object, annex, &buffer, 1); + bufstr = (char *) buffer; if (transferred < 0) return NULL; @@ -2390,11 +2391,11 @@ target_read_stralloc (struct target_ops *ops, enum target_object object, if (transferred == 0) return xstrdup (""); - buffer[transferred] = 0; + bufstr[transferred] = 0; /* Check for embedded NUL bytes; but allow trailing NULs. */ - for (i = strlen (buffer); i < transferred; i++) - if (buffer[i] != 0) + for (i = strlen (bufstr); i < transferred; i++) + if (bufstr[i] != 0) { warning (_("target object %d, annex %s, " "contained unexpected null characters"), @@ -2402,7 +2403,7 @@ target_read_stralloc (struct target_ops *ops, enum target_object object, break; } - return buffer; + return bufstr; } /* Memory transfer methods. */ @@ -3542,11 +3543,12 @@ target_fileio_read_alloc (const char *filename, gdb_byte **buf_p) char * target_fileio_read_stralloc (const char *filename) { - char *buffer; + gdb_byte *buffer; + char *bufstr; LONGEST i, transferred; - transferred = target_fileio_read_alloc_1 (filename, - (gdb_byte **) &buffer, 1); + transferred = target_fileio_read_alloc_1 (filename, &buffer, 1); + bufstr = (char *) buffer; if (transferred < 0) return NULL; @@ -3554,11 +3556,11 @@ target_fileio_read_stralloc (const char *filename) if (transferred == 0) return xstrdup (""); - buffer[transferred] = 0; + bufstr[transferred] = 0; /* Check for embedded NUL bytes; but allow trailing NULs. */ - for (i = strlen (buffer); i < transferred; i++) - if (buffer[i] != 0) + for (i = strlen (bufstr); i < transferred; i++) + if (bufstr[i] != 0) { warning (_("target file %s " "contained unexpected null characters"), @@ -3566,7 +3568,7 @@ target_fileio_read_stralloc (const char *filename) break; } - return buffer; + return bufstr; } -- 2.30.2