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]

About *printf %n fortifications


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]