This is the mail archive of the libc-alpha@sourceware.org mailing list for the glibc project.
Index Nav: | [Date Index] [Subject Index] [Author Index] [Thread Index] | |
---|---|---|
Message Nav: | [Date Prev] [Date Next] | [Thread Prev] [Thread Next] |
Other format: | [Raw text] |
Hi, Why a printf() with %n in the format string would require this string to be non-writable? (debug/tst-chk1.c, stdio-common/vfprintf.c) See the attached test case (-O2 -D_FORTIFY_SOURCE=2) char fmt[] = "%s%n\n"; printf(fmt, "bar", &count); looks valid to me, but causes an abort() with *** %n in writable segment detected *** The check probably meant to be against the %n argument itself. The following patch fixes this but I have not updated tst-chk1.c yet. WDYT? 2006-02-24 Gwenole Beauchesne <gbeauchesne@mandriva.com> * stdio-common/vfprintf.c (vfprintf): Fix fortify checks for %n specifier. --- glibc-2.3.6/stdio-common/vfprintf.c.vfprintf-fortify-form-number 2004-11-25 17:40:23.000000000 +0100 +++ glibc-2.3.6/stdio-common/vfprintf.c 2006-02-24 16:46:57.000000000 +0100 @@ -882,44 +882,46 @@ vfprintf (FILE *s, const CHAR_T *format, /* NOTREACHED */ \ \ LABEL (form_number): \ - if (s->_flags2 & _IO_FLAGS2_FORTIFY) \ - { \ - if (! readonly_format) \ - { \ - extern int __readonly_area (const void *, size_t) \ - attribute_hidden; \ - readonly_format \ - = __readonly_area (format, ((STR_LEN (format) + 1) \ - * sizeof (CHAR_T))); \ - } \ - if (readonly_format < 0) \ - __libc_fatal ("*** %n in writable segment detected ***\n"); \ - } \ - /* Answer the count of characters written. */ \ - if (fspec == NULL) \ - { \ - if (is_longlong) \ - *(long long int *) va_arg (ap, void *) = done; \ - else if (is_long_num) \ - *(long int *) va_arg (ap, void *) = done; \ - else if (is_char) \ - *(char *) va_arg (ap, void *) = done; \ - else if (!is_short) \ - *(int *) va_arg (ap, void *) = done; \ - else \ - *(short int *) va_arg (ap, void *) = done; \ - } \ - else \ + /* Pointer to signed integer. */ \ + { \ + const void *ptr; \ + if (fspec == NULL) \ + ptr = va_arg (ap, void *); \ + else \ + ptr = args_value[fspec->data_arg].pa_pointer; \ + \ + if (s->_flags2 & _IO_FLAGS2_FORTIFY) \ + { \ + extern int __readonly_area (const void *, size_t) \ + attribute_hidden; \ + \ + int objsize; \ + if (is_longlong) \ + objsize = sizeof(long long int); \ + else if (is_long_num) \ + objsize = sizeof(long int); \ + else if (is_char) \ + objsize = 1; \ + else if (!is_short) \ + objsize = sizeof(int); \ + else \ + objsize = sizeof(short); \ + if (__readonly_area (ptr, objsize) > 0) \ + __libc_fatal ("*** %n into read-only segment detected ***\n"); \ + } \ + \ + /* Answer the count of characters written. */ \ if (is_longlong) \ - *(long long int *) args_value[fspec->data_arg].pa_pointer = done; \ + *(long long int *) ptr = done; \ else if (is_long_num) \ - *(long int *) args_value[fspec->data_arg].pa_pointer = done; \ + *(long int *) ptr = done; \ else if (is_char) \ - *(char *) args_value[fspec->data_arg].pa_pointer = done; \ + *(char *) ptr = done; \ else if (!is_short) \ - *(int *) args_value[fspec->data_arg].pa_pointer = done; \ + *(int *) ptr = done; \ else \ - *(short int *) args_value[fspec->data_arg].pa_pointer = done; \ + *(short int *) ptr = done; \ + } \ break; \ \ LABEL (form_strerror): \
Attachment:
tst-printf-fortify.c
Description: Text document
Index Nav: | [Date Index] [Subject Index] [Author Index] [Thread Index] | |
---|---|---|
Message Nav: | [Date Prev] [Date Next] | [Thread Prev] [Thread Next] |