Bugtraq mailing list archives

Poor man's solution to format bugs


From: Mike Frantzen <frantzen () EXPERT CC PURDUE EDU>
Date: Tue, 25 Jul 2000 19:31:41 -0500

/*
 * This is a kludgy example of a source level workaround to the now
 * infamous format bugs.  It should work for newer versions of gcc.  Older
 * versions should work as well but you can use recursive macros.
 *
 * It uses a set of variable arguement macros to wrap variable arguement
 * functions.  It counts the number of arguements and passes the count
 * to a wrapper function.  Now it has a count of the passed arguements.
 *
 * It should be relatively easy to apply the technique to other vulnerable
 * functions.  Care would have to be taken in multithreaded programs to
 * use a thread specific data.
 * Stick the macros into the standard include's and a slight hack to LD_PRELOAD
 * or libc.  Those of us who are not Theo get some semblance of protection ;)
 *
 * I'm sure someone with more sleep will improve on the concept.
 *
 * See the gcc info pages for an explaination of variable arguement macros.
 * I'm too tired to explain them.  You may want to run 'gcc -E' against it
 * to see how they expand.
 *
 * gcc -v
 * Reading specs from /usr/local/lib/gcc-lib/sparc-sun-solaris2.7/2.95.2/specs
 * gcc version 2.95.2 19991024 (release)
 *
 * Program output:
 *  none
 *  one 1
 *  two 1 2
 *  three 1 2 3
 *  Aiieee.  Arguement count mismatch of 1.
 *  Aiieee.  Arguement count mismatch of -1.
 *
 *
 * As always, pardon the spelling errors.  Bad english is by native language.
 * See you all at defcon.
 */


#include <stdio.h>
#include <stdio.h>
#include <varargs.h>


/* Could stick this stuff into an include file */
#define printf                  mikes_print(&cnt, print0

#define print0(x, args...)      x ,print1(## args)
#define print1(x, args...)      x+(++cnt-cnt) ,print2(## args)
#define print2(x, args...)      x+(++cnt-cnt) ,print3(## args)
#define print3(x, args...)      x+(++cnt-cnt) ,print4(## args)
#define print4(x, args...)      x+(++cnt-cnt) ,print5(## args)
#define print5(x, args...)      x+(++cnt-cnt) ,print6(## args)
#define print6(x, args...)      x+(++cnt-cnt) ,print7(## args)
#define print7(x, args...)      x+(++cnt-cnt) ,print8(## args)
#define print8(x, args...)      x+(++cnt-cnt) ,print9(## args)
#define print9(x, args...)      Need_to_make_more_print_statements
/* END include stuff */


void mikes_print(int *args, char *format, ...);

/* Arguement counter */
int cnt = 0;

int main(void)
{

  printf("none\n");
  printf("one %d\n", 1);
  printf("two %d %d\n", 1, 2);
  printf("three %d %d %d\n", 1, 2, 3);
  printf("explode %x %n %p\n", 1, 2, 3, 4);
  printf("explode %d %p %n %d %d\n", 1, 2, 3, 4);

  return 0;
}


/*
 * Simply counts the % tokens in the function.
 * Bomb out if they don't match *args.
 */
void mikes_print(int *args, char *format, ...)
{
  va_list ap;
  char *rptr;

  for (rptr = format; *rptr; rptr++)
    if (*rptr == '%')
      if (*++rptr != '%')
        (*args)--;

  if (*args) {
    fprintf(stderr, "Aiieee.  Arguement count mismatch of %d.\n", *args);
    *args = 0;
    return;
  }

  /* Must turn counter back to 0 */
  *args = 0;

  va_start(ap);
  vprintf(format, ap);
  va_end(ap);
}


Current thread: