I'm trying to debug a program that gives the error: Abort (core dumped). Valgrind detects a stack smashing and gives a LEAK SUMMARY with 1 block still reachable. It signals to line 12 of a the function downloadAndOpen where I have an fopen that I thought was closed at the end of main but it seems like it isn't. I would appreciate help with this bug. The valgrind output is:
*** stack smashing detected ***: ./mtg terminated
==9594==
==9594== HEAP SUMMARY:
==9594== in use at exit: 352 bytes in 1 blocks
==9594== total heap usage: 1 allocs, 0 frees, 352 bytes allocated
==9594==
==9594== 352 bytes in 1 blocks are still reachable in loss record 1 of 1
==9594== at 0x402A17C: malloc (in /usr/lib/valgrind/vgpreload_memcheck-x86-linux.so)
==9594== by 0x40BE62B: __fopen_internal (iofopen.c:73)
==9594== by 0x40BE70A: fopen@@GLIBC_2.1 (iofopen.c:103)
==9594== by 0x8048729: downloadAndOpen (downloadAndOpen.c:12)
==9594== by 0x80485B5: main (mtg.c:15)
==9594==
==9594== LEAK SUMMARY:
==9594== definitely lost: 0 bytes in 0 blocks
==9594== indirectly lost: 0 bytes in 0 blocks
==9594== possibly lost: 0 bytes in 0 blocks
==9594== still reachable: 352 bytes in 1 blocks
==9594== suppressed: 0 bytes in 0 blocks
==9594==
==9594== For counts of detected and suppressed errors, rerun with: -v
==9594== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
Aborted (core dumped)
Edit: After fixing the first problem I got a similar one after the program worked correctly until page 18. The Valgrind report is:
==11845== Invalid read of size 4
==11845== at 0x40C5F35: getc (getc.c:38)
==11845== by 0x80487EA: download (download.c:12)
==11845== by 0x2020201F: ???
==11845== Address 0x420ba20 is 248 bytes inside a block of size 352 free'd
==11845== at 0x402B358: free (in /usr/lib/valgrind/vgpreload_memcheck-x86-linux.so)
==11845== by 0x40BDDB9: fclose@@GLIBC_2.1 (iofclose.c:85)
==11845== by 0x804866B: main (mtg.c:26)
==11845==
==11845== Invalid read of size 4
==11845== at 0x40C5F3E: getc (getc.c:38)
==11845== by 0x80487EA: download (download.c:12)
==11845== by 0x2020201F: ???
==11845== Address 0x420ba68 is 320 bytes inside a block of size 352 free'd
==11845== at 0x402B358: free (in /usr/lib/valgrind/vgpreload_memcheck-x86-linux.so)
==11845== by 0x40BDDB9: fclose@@GLIBC_2.1 (iofclose.c:85)
==11845== by 0x804866B: main (mtg.c:26)
==11845==
==11845== Invalid read of size 4
==11845== at 0x40C5F48: getc (getc.c:38)
==11845== by 0x80487EA: download (download.c:12)
==11845== by 0x2020201F: ???
==11845== Address 0x8 is not stack'd, malloc'd or (recently) free'd
==11845==
==11845==
==11845== Process terminating with default action of signal 11 (SIGSEGV)
==11845== Access not within mapped region at address 0x8
==11845== at 0x40C5F48: getc (getc.c:38)
==11845== by 0x80487EA: download (download.c:12)
==11845== by 0x2020201F: ???
==11845== If you believe this happened as a result of a stack
==11845== overflow in your program's main thread (unlikely but
==11845== possible), you can try to increase the size of the
==11845== main thread stack using the --main-stacksize= flag.
==11845== The main thread stack size used in this run was 8388608.
==11845==
==11845== HEAP SUMMARY:
==11845== in use at exit: 352 bytes in 1 blocks
==11845== total heap usage: 18 allocs, 17 frees, 6,336 bytes allocated
==11845==
==11845== 352 bytes in 1 blocks are still reachable in loss record 1 of 1
==11845== at 0x402A17C: malloc (in /usr/lib/valgrind/vgpreload_memcheck-x86-linux.so)
==11845== by 0x40BE62B: __fopen_internal (iofopen.c:73)
==11845== by 0x40BE70A: fopen@@GLIBC_2.1 (iofopen.c:103)
==11845== by 0x8048729: downloadAndOpen (downloadAndOpen.c:12)
==11845== by 0x80485B5: main (mtg.c:15)
==11845==
==11845== LEAK SUMMARY:
==11845== definitely lost: 0 bytes in 0 blocks
==11845== indirectly lost: 0 bytes in 0 blocks
==11845== possibly lost: 0 bytes in 0 blocks
==11845== still reachable: 352 bytes in 1 blocks
==11845== suppressed: 0 bytes in 0 blocks
==11845==
==11845== For counts of detected and suppressed errors, rerun with: -v
==11845== ERROR SUMMARY: 3 errors from 3 contexts (suppressed: 0 from 0)
Segmentation fault (core dumped)
I've isolated the problem but I still can't see what's wrong:
#include <stdio.h>
#include <stdlib.h> // for using system calls
#include <stdbool.h>
int main (void)
{
char url[200], cmd[200];
int pos = 0, c, j;
bool found = false;
FILE *fp;
fp = fopen ("file.txt", "w+");
fprintf (fp, "\"http://4.bp.blogspot.com/-mIE4JlppKMU/T9_mxKR__wI/AAAAAAAAASs/deHLBL21ZbE/s640/Temple Garden.png\"");
while (!found)
{
if ( (c = getc (fp)) == EOF ) {
printf ("Image not found\n");
return 1;
}
printf ("%c", c);
url[pos] = c;
if ( pos > 0 && url[pos-1] == 'g' && url[pos] == '\"' )
{
found = true;
}
++pos;
}
--pos;
char url2[pos];
for ( j = 1; j < pos; j++ )
{
url2[j - 1] = url[j];
}
url2[j - 1] = '\0';
//http://joequery.me/code/snprintf-c/
// wget -q for quiet -nc, --no-clobber skip downloads that would download to existing files (no sobreescribir)
snprintf(cmd, 200, "wget -q -nc -O /home/arturo/Dropbox/Digital_Renders/%d \'%s\'", 1, url2);
system(cmd);
return 0;
}
Here is the code of the main function:
#include "helpers.h"
char postBegin[] = "forum-post-body-content", postEnd[] = "p-comment-notes", img[] = "img src=";
int length1 = 22, length2 = 14, length3 = 7;
int pos1 = 0, pos2 = 0, pos3 = 0;
int main ()
{
bool inPost = false;
FILE *fp;
int c;
for ( int i = 1; i <= 151; i++ )
{
downloadAndOpen (&fp, i);
while ( (c = getc (fp)) != EOF ) {
if ( search (postBegin, length1, c, &pos1) )
inPost = true;
if (inPost) {
if ( search (postEnd, length2, c, &pos2) )
inPost = false;
if ( search (img, length3, c, &pos3) )
download (&fp);
}
}
fclose (fp);
}
}
And this is the function where Valgrind complains:
#include "helpers.h"
void downloadAndOpen (FILE **fp, int i)
{
char cmd[128]={0}, file[20];
// download web page
sprintf (cmd, "wget -q -O page%d.txt 'http://www.mtgsalvation.com/forums/creativity/artwork/340782-official-digital-rendering-thread?page=%d'", i, i);
system (cmd);
// open text file
sprintf (file, "page%d.txt", i);
*fp = fopen (file, "r");
}
The rest of the program is here:
#include <stdio.h>
#include <stdlib.h> // for using system calls
#include <stdbool.h>
#include <string.h> // for strlen
void downloadAndOpen (FILE **fp, int i);
bool search (char needle[], int length, char c, int *pos);
void download (FILE* *fp);
#include "helpers.h"
void download (FILE **fp)
{
char url[128], cmd[128];
int pos = 0, c, j;
static int num = 1;
bool found = false;
while (!found)
{
if ( (c = getc (*fp)) == EOF ) {
printf ("Image not found\n");
return;
}
url[pos] = c;
if ( pos > 0 && url[pos-1] == 'g' && url[pos] == '\"' )
{
found = true;
}
++pos;
}
--pos;
char url2[pos];
for ( j = 1; j < pos; j++ )
{
url2[j - 1] = url[j];
}
url2[j - 1] = '\0';
sprintf(cmd, "wget -q -O /home/arturo/Dropbox/Digital_Renders/%d \'%s\'", num++, url2);
system(cmd);
}
#include "helpers.h"
bool search (char needle[], int length, char c, int *pos)
{
if (needle[*pos] == c)
{
if (*pos == length)
{
return true;
*pos = -1;
}
(*pos)++;
}
else
{
if(*pos > 0)
*pos = 0;
}
return false;
}
And the Makefile:
CC = gcc
CFLAGS = -ggdb3 -O0 -std=c99 -Wall -Werror
all: mtg
mtg: mtg.c downloadAndOpen.c search.c download.c helpers.h
$(CC) $(CFLAGS) -o mtg mtg.c downloadAndOpen.c search.c download.c
clean:
rm -f *.o a.out core mtg
You may have buffer overflows in both of these sprintf
commands:
char cmd[128]={0}, file[20];
sprintf (cmd, "wget -q -O page%d.txt 'http://www.mtgsalvation.com/forums/creativity/artwork/340782-official-digital-rendering-thread?page=%d'", i, i);
sprintf (file, "page%d.txt", i);
Rather than try to analyze whether a particular instance overflowed or not, fix your code:
int n = snprintf(cmd, sizeof cmd, "............
if ( n < 0 || n >= sizeof cmd )
exit(EXIT_FAILURE); // or other error handling
and
n = snprintf(file, sizeof file, "page%d.txt", i);
if ( n < 0 || n >= sizeof file )
exit(EXIT_FAILURE); // or other error handling
If you make this change and still get the problem then update your post.