Lectura no válida del tamaño 1 en strstr() usando valgrind

Estoy inspeccionando un fragmento de código con valgrind y me sale este error:

==7001== Invalid read of size 1
==7001==    at 0x402E21B: strstr (in /usr/lib/valgrind/vgpreload_memcheck-x86-linux.so)
==7001==    by 0x8049742: replace_in_file (functions.c:191)
==7001==    by 0x8049C55: parse_dir (functions.c:295)
==7001==    by 0x8049059: main (main.c:214)
==7001==  Address 0x42018c3 is 0 bytes after a block of size 3 alloc'd
==7001==    at 0x402B018: malloc (in /usr/lib/valgrind/vgpreload_memcheck-x86-linux.so)
==7001==    by 0x80496EC: replace_in_file (functions.c:183)
==7001==    by 0x8049C55: parse_dir (functions.c:295)
==7001==    by 0x8049059: main (main.c:214)

El fragmento de código tiene el siguiente aspecto:

long int replace_in_file(char **sets, FILE *file, char *path, const char *mode){
    long int n = 0, size = 0, len, remaining_len;

    char *buffer,
         *found,
         *before,
         *after;

    size = file_size(file);
    if(-1 != size){

        buffer = malloc(size * sizeof(char));

        rewind(file);
        fread(buffer, 1, size, file);

        int i=0;
        do{
            do{
                found = strstr(buffer, sets[i]); // LINE 191
                if(NULL != found && '\0' != sets[i][0]){

//rest of code...

No puedo darme cuenta por qué recibo ese error, porque todo funciona como se esperaba y en el depurador todas las variables parecen estar bien.

¿Qué está mal, cómo puedo solucionarlo?

preguntado el 03 de mayo de 12 a las 17:05

¿Puedes garantizar que buffer es Nul-terminado después de la fread()? noto que no bzero() eso o cualquier cosa. -

¿Cuántos punteros (char *) hay en la matriz (conjuntos)? ¿Es posible que sets[i] tenga un valor para i que lo coloque fuera de la matriz (sets)? Además, ¿cómo se garantiza que (el búfer) terminará en NUL? fread() no hará eso por ti... -

¿Hay alguna posibilidad de que file_size devuelva 0? Yo usaría if(size > 0) en tu condicional. -

Resuelto, @chrisaycock, agrega tu respuesta para que pueda aceptarla, ese era el problema. Jeremy Friesner, vi tu respuesta después de resolverlo. -

Bien, lo publiqué como respuesta. También deberías votar Error fatal ya que encontró el mismo error. -

3 Respuestas

fread()no anular los datos que lee, pero strstr() espera una cadena terminada en NUL. Debe asignar tamaño + 1 bytes y agregar explícitamente el terminador nul para estar seguro.

contestado el 03 de mayo de 12 a las 17:05

Tus buffer no tiene terminación nula. Por lo general, solo puede bzero() antes de la fread() para asegurarse de que funcionará con strstr() y funciones similares.

contestado el 03 de mayo de 12 a las 17:05

de lo que leí en mi página de manual, fread() no NULL-terminar su resultado de acuerdo con C89 - y tampoco en mi sistema - así que strstr() simplemente leerá el final de buffer a menos que lo termine, por ejemplo, así

buffer = malloc((size + 1) * sizeof(char));
memset(buffer, '\0', size + 1);

(que tiene la ventaja de terminarlo también en caso de que fread no pueda leer todo el archivo)

una nota al margen: dado que ya usas sizeof(char) en tu malloc() llamada, también podría considerar reemplazar el 1 en la fread() en aras de la consistencia.

contestado el 03 de mayo de 12 a las 18:05

No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas or haz tu propia pregunta.