fscanf out of bounds write

Bug #110917 reported by Alysander
2
Affects Status Importance Assigned to Milestone
glibc (Ubuntu)
Invalid
Undecided
Unassigned

Bug Description

Hi,
I am learning C and had a strange bug when allocating values into some calloc'd memory with fscanf.
Later calls to fscanf would overwrite previously set values to zero. I am using an AMD athlon 64 bit cpu on
a 32bit Fiesty Fawn version of Ubuntu and I think that the std library must be ignoring the type conversion modifier
and just writing a larger type into the memory.
Attached is a simple program called fscanfbug.c which reproduces the problem.
Is this something I should just work around or should this be fixed in glibc?
Thanks,
     Alysander

//Number 5
#include <stdio.h>
#include <stdlib.h>
#include <inttypes.h>

int main (int argc, char *argv[]) {
  int8_t *numarray = NULL;
  FILE *numfile = NULL;
  numarray = calloc(10, sizeof(int8_t));
  numfile = fopen("fscanfbug.c", "r");
  fscanf(numfile, "//Number %"PRId8, &numarray[8]);
  fscanf(numfile, "//Number %"PRId8, &numarray[7]);
  printf("The 8th number is: %"PRId8"\n", numarray[8]);
  printf("The 7th number is: %"PRId8" (shouldn't this be the same as above?) \n", numarray[7]);
  fclose(numfile);
  free(numarray);
  return 1;
}

Revision history for this message
Tollef Fog Heen (tfheen) wrote :

You need to check the return value of your calls; the second fscanf does not match anything and therefore doesn't assign anything.

//Number 5
#include <stdio.h>
#include <stdlib.h>
#include <inttypes.h>

int main (int argc, char *argv[]) {
  int8_t *numarray = NULL;
  FILE *numfile = NULL;
  int ret;
  numarray = calloc(10, sizeof(int8_t));
  if (! numarray)
    perror("calloc");
  numfile = fopen("fscanfbug.c", "r");
  if (! numfile)
    perror("fopen");
  if (fscanf(numfile, "//Number %"PRId8, &numarray[8]) != 1)
    printf("First fscanf returned wrong number of elements\n");
  if (fscanf(numfile, "//Number %"PRId8, &numarray[7]) != 1)
    printf("Second fscanf returned wrong number of elements\n");
  printf("The 8th number is: %"PRId8"\n", numarray[8]);
  printf("The 7th number is: %"PRId8" (shouldn't this be the same as above?) \n", numarray[7]);
  fclose(numfile);
  free(numarray);
  return 1;
}

if you run this, you will see that it complains at the second fscanf.

Changed in glibc:
status: Unconfirmed → Rejected
Revision history for this message
Alysander (alysander) wrote : Maybe it's inttypes.h

Thanks! I see now that the example was not working because fscanf had simply continued onwards and wasn't finding the information correctly formatted and hence did not set the value. However, if you correct that mistake the original problem still exists (file attached).

Furthermore, when compiling with the " -Wall -std=c99" options in gcc 4.1.2 (Ubuntu 4.1.2-0ubuntu4) it says:

fscanfbug.c:17: warning: format ‘%d’ expects type ‘int *’, but argument 3 has type ‘int8_t *’

So it appears that the PRId8 macro is being incorrectly defined as "d" on my machine when it should in fact be "hhd", leading to the byte overwrites I mentioned initially. Finally, adding the extra two h's corrects the problem.

Maybe there is a bug in inttypes for AMD Athlon 64 cpus?

Revision history for this message
Tollef Fog Heen (tfheen) wrote : Re: [Bug 110917] Maybe it's inttypes.h

* Alysander

| So it appears that the PRId8 macro is being incorrectly defined as "d"
| on my machine when it should in fact be "hhd", leading to the byte
| overwrites I mentioned initially. Finally, adding the extra two h's
| corrects the problem.

PRId8 is, as you can guess from the name (and from the comment in
inttypes.h) used for printing. You probably rather want SCNd8 which
is defined as "hhd" and used for scanning.

--
Tollef Fog Heen
UNIX is user friendly, it's just picky about who its friends are

To post a comment you must log in.
This report contains Public information  
Everyone can see this information.

Other bug subscribers

Bug attachments

Remote bug watches

Bug watches keep track of this bug in other bug trackers.