Stack smashing while casting and copying from one buffer to another - c

I have a problem writing 8 alphanumeric symbols into my dest_buffer buffer.
I want to convert a char from buff to hexadecimal, then store the value in
different cases of my dest_buffer buffer.
For example:
buff[0] = 58 should give me dest_buffer[0] = '3' and dest_buffer[1] = 'a'
and so on to reach 8 chars.
src is a char[8*sizeof(int)+1] and buff is the same.
Unfortunatly, I only have this output:
2dbb771
*** stack smashing detected ***: ./a.out terminated
[1] 9843 abort (core dumped) ./a.out
This is the loop I use to do the job
for (i = 0; i < 4*sizeof(int); ++i)
{
snprintf (
&dest_buff[i*sizeof(int)*2],
sizeof(int)*2,
"%x",
*(int*)&buff[i * sizeof(int)]
) ;
}
I know I'm missing something but I don't know what, neither where, could
any of you help me?
Thanks
EDIT 1:
Here is another part of my code to be more precise:
int i, rndf ;
char buff[4*sizeof(int)+1];
rndf = open("/dev/urandom", O_RDONLY) ;
if( read (rndf, buff, 4*sizeof(int)) < 0)
{
fprintf (stderr, "%s\n", "An error occured while reading urandom") ;
exit (EXIT_FAILURE) ;
}
close(rndf) ;
after this come the loop

You have stack corruption because char buff[4*sizeof(int)+1]; is your variable.
Let's assume sizeof(int) is 4 bytes. Then variable size is 17 bytes.
By doing this: &dest_buff[i*sizeof(int)*2] you are at some time accessing (when i = 3) address offset 3 * 4 * 2 = 24 which is out of range of your variable.
Conclusion: you have undefined behaviour. Increase variable length or correct you pointer usage.

Related

Xcode debugger messing with input

I'm writing a simple tokenizer in C and when I use the Xcode console to run my code and give input to my lexer, sometimes it's adding weird characters onto the end of my input.
Here's an input that sometimes gets extra characters added onto it
The input is on the line starting with (>>) and the data I print from the buffer is below it. You can see extra characters "\357 \234 1" somehow made their way into the buffer.
>> 2147483618
num read: 14
2 1 4 7 4 8 3 6 1 8 \357 \234 1
I thought it was an overflow problem, but it only happens when I run my code through the Xcode debugger.
Here's what happens when I just use the Terminal to execute my code
>> 2147483618
num read: 11
2 1 4 7 4 8 3 6 1 8
Here's my C code for reading in characters from the user:
for (;;) {
char *buff = malloc(20 * sizeof(char));
// Max number of characters to read
size_t num_to_read = 0;
// Number of characters actually read
size_t num_read = 0;
num_read = getline (&buff, &num_to_read, stdin);
printf("num read: %d\n", num_read);
// Code to print out the buffer
for (int i = 0; i < num_read; i++) {
if (buff[i] == '\0')
break;
printf("%c ",buff[i]);
}
free(buff);
}
Does anyone have any idea what's causing this?

Segmentation fault

#include <stdio.h>
int main(void)
{
/* an array with 5 rows and 2 columns*/
char* a[5][2];
int y, p;
for(y = 0; y < 5; y++)
{
for(p = 0; p < 2; p++)
{
scanf("%s", a[y][p]);
}
}
int i, j;
/* output each array element's value */
for ( i = 0; i < 5; i++ )
{
for ( j = 0; j < 2; j++ )
{
printf("a[%d][%d] = %s\n", i,j, a[i][j] );
}
}
return 0;
}
I've been getting a Segmentation fault as an output of this program after inserting 2 strings. Can anyone tell me what's wrong with my code?
Problem:
You're declaring 10 uninitialized pointers here:
char* a[5][2];
And then trying to fill them with data:
scanf("%s", a[y][p]);
This is wrong. You need to allocate memory before copying data.
Solution:
I would do this in a more sexy way, but the quick solution would be:
#define MAX_LEN 100
char a[5][2][MAX_LEN];
/* ... */
scanf("%s", a[y][p][0]);
Just a hint on helping troubleshoot. Hope this will help the future readers who are new to pointers.
A better way to troubleshoot a segmentation fault is to run it with a debugger like gdb.
e.g
Compile your program with gdb (You need gdb installed on your host)
gcc -ggdb Test.c -o Test
Then run it with gdb
gdb ./Test
In your case, you will see an output like this. It'll go to the gdb prompt.
Then type run or r, it will run the program. Then it asks for an input. Type your input value. Then the segmentation fault occurs. Now you can see your backtrace by typing backtrace or bt. You can see which line causes your crash. You can see the code by list. You can go to any line by typeing list <line>. Go through a GDB Guide to find out more commands.
It tries to access a pointer, probably invalid that's why it crashes. Then find out why it's invalid. Probably you didn't initialize it or didn't allocate memory. So the easiest fix would be to declare it as an array (rather than a pointer array) like #Andrewjs mentioned in his answer.
Reading symbols from /tmp/Examples/Test...done.
(gdb) run
Starting program: /tmp/Examples/Test
for 1
for 2
10
Program received signal SIGSEGV, Segmentation fault.
0x005c5c3d in _IO_vfscanf_internal (s=0x6d1420, format=0x804867e "%s", argptr=0xbfffe984 "\020\204\004\b", errp=0x0) at vfscanf.c:840
840 *str++ = c;
(gdb) backtrace
#0 0x005c5c3d in _IO_vfscanf_internal (s=0x6d1420, format=0x804867e "%s", argptr=0xbfffe984 "\020\204\004\b", errp=0x0) at vfscanf.c:840
#1 0x005cebbb in __scanf (format=0x804867e "%s") at scanf.c:35
#2 0x0804850d in main () at Test.c:16 <-- Your program's last call
(gdb) list
835 }
836 #else
837 /* This is easy. */
838 if (!(flags & SUPPRESS))
839 {
840 *str++ = c; <-- Crash point
841 if ((flags & MALLOC)
842 && (char *) str == *strptr + strsize)
843 {
844 /* Enlarge the buffer. */
(gdb)
For advance debugging of applications This may help

Segmentation fault when reading space separated values from file in C

I have an input file which contains space separated values
AA BB 4
A B
AB BA
AA CC
CC BB
A B 3
A C
B C
c B
I want content of the first line moved to s1, s2 and n respectively
and next n lines contents 2 space separated strings these will move to
production_left and production_right respectively.
The layout will be repeated for subsequent blocks of lines also. The sample data has two blocks of input.
My code given below
int main()
{
char *s1[20], *t1[20];
char *production_left[20], *production_right[20];
int n;
FILE *fp;
fp = fopen("suffix.txt","r");
int iss=0;
do{
fscanf(fp,"%s %s %d",s1[iss],t1[iss],&n);
int i=0;
while(i<n)
{
fscanf(fp,"%s %s",production_left[i],production_right[i]);
i++;
}
}while(!eof(fp));
}
Every time it is giving segmentation fault.
A lot of C, is just keeping clear in your mind, what data you need available in what scope (block) of your code. In your case, the data you are working with is the first (or header) line for each section of your data file. For that you have s1 and t1, but you have nothing to preserve n so that it is available for reuse with your data. Since n holds the number of indexes to expect for production_left and production_right under each heading, simply create an index array, e.g. int idx[MAXC] = {0}; to store each n associated with each s1 and t1. That way you preserve that value for use in iteration later on. (MAXC is just a defined constant for 20 to prevent using magic numbers in your code)
Next, you need to turn to your understanding of pointer declarations and their use. char *s1[MAXC], *t1[MAXC], *production_left[MAXC], *production_right[MAXC]; declares 4 array of pointers (20 pointers each) for s1, t1, production_left and production_right. The pointers are uninitialized and unallocated. While each can be initialized to a pointer value, there is no storage (allocated memory) associated with any of them that would allow copying data. You can't simply use fscanf and assign the same pointer value to each (they would all end up pointing to the last value -- if it remained in scope)
So you have two choices, (1) either use a 2D array, or (2) allocate storage for each string and copy the string to the new block of memory and assign the pointer to the start of that block to (e.g. s1[x]). The strdup function provides the allocate and copy in a single function call. If you do not have strdup, it is a simple function to write using strlen, malloc and memcopy (use memmove if there is a potential that the strings overlap).
Once you have identified what values you need to preserve for later use in your code, you have insured the variables declared are scoped properly, and you have insured that each is properly initialized and storage allocated, all that remains is writing the logic to make things work as you intend.
Before turning to an example, it is worth noting that you are interested in line-oriented input with your data. The scanf family provides formatted input, but often it is better to use a line-oriented function for the actual input (e.g. fgets) and then a separate parse with, e.g. sscanf. In this case it is largely a wash since your first values are string values and the %s format specifier will skip intervening whitespace, but that is often not the case. For instance, you are effectively reading:
char tmp1[MAXC] = "", tmp2[MAXC] = "";
...
if (fscanf (fp, "%s %s %d", tmp1, tmp2, &n) != 3)
break;
That can easily be replaced with a bit more robust:
char buf[MAXC] = "", tmp1[MAXC] = "", tmp2[MAXC] = "";
...
if (!fgets (buf, sizeof buf, fp) ||
sscanf (buf, "%s %s %d", tmp1, tmp2, &n) != 3)
break;
(which will validate both the read and the conversion separately)
Above, also note the use of temporary buffers tmp1 and tmp2 (and buf for use with fgets) It is very often advantageous to read input into temporary values that can be validated before final storage for later use.
What remains is simply putting the pieces together in the correct order to accomplish your goals. Below is an example that reads data from the filename given as the first argument (or from stdin if no filename is given) and then outputs the data and frees all memory allocated before exiting.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAXC 20
int main (int argc, char **argv) {
char *s1[MAXC], *t1[MAXC],
*production_left[MAXC], *production_right[MAXC];
int idx[MAXC] = {0}, /* storage for 'n' values */
iss = 0, ipp = 0, pidx = 0;
FILE *fp = argc > 1 ? fopen (argv[1], "r") : stdin;
if (!fp) { /* validate file open for reading */
fprintf (stderr, "error: file open failed '%s'.\n", argv[1]);
return 1;
}
/* loop until no header row read, protecting array bounds */
for (; ipp < MAXC && iss < MAXC; iss++) {
char buf[MAXC] = "", tmp1[MAXC] = "", tmp2[MAXC] = "";
int n = 0;
if (!fgets (buf, sizeof buf, fp) ||
sscanf (buf, "%s %s %d", tmp1, tmp2, &n) != 3)
break;
idx[iss] = n;
s1[iss] = strdup (tmp1); /* strdup - allocate & copy */
t1[iss] = strdup (tmp2);
if (!s1[iss] || !t1[iss]) { /* if either is NULL, handle error */
fprintf (stderr, "error: s1 or s1 empty/NULL, iss: %d\n", iss);
return 1;
}
/* read 'n' data lines from file, protecting array bounds */
for (int i = 0; i < n && ipp < MAXC; i++, ipp++) {
char ptmp1[MAXC] = "", ptmp2[MAXC] = "";
if (!fgets (buf, sizeof buf, fp) ||
sscanf (buf, "%s %s", ptmp1, ptmp2) != 2) {
fprintf (stderr, "error: read failure, ipp: %d\n", iss);
return 1;
}
production_left[ipp] = strdup (ptmp1);
production_right[ipp] = strdup (ptmp2);
if (!production_left[ipp] || !production_right[ipp]) {
fprintf (stderr, "error: production_left or "
"production_right empty/NULL, iss: %d\n", iss);
return 1;
}
}
}
if (fp != stdin) fclose (fp); /* close file if not stdin */
for (int i = 0; i < iss; i++) {
printf ("%-8s %-8s %2d\n", s1[i], t1[i], idx[i]);
free (s1[i]); /* free s & t allocations */
free (t1[i]);
for (int j = pidx; j < pidx + idx[i]; j++) {
printf (" %-8s %-8s\n", production_left[j], production_right[j]);
free (production_left[j]); /* free production allocations */
free (production_right[j]);
}
pidx += idx[i]; /* increment previous index value */
}
return 0;
}
Example Input File
$ cat dat/production.txt
AA BB 4
A B
AB BA
AA CC
CC BB
A B 3
A C
B C
c B
Example Use/Output
$ ./bin/production <dat/production.txt
AA BB 4
A B
AB BA
AA CC
CC BB
A B 3
A C
B C
c B
Memory Use/Error Check
In any code you write that dynamically allocates memory, you have 2 responsibilities regarding any block of memory allocated: (1) always preserve a pointer to the starting address for the block of memory so, (2) it can be freed when it is no longer needed.
It is imperative that you use a memory error checking program to insure you do not attempt to write beyond/outside the bounds of your allocated block of memory, attempt to read or base a conditional jump on an uninitialized value, and finally, to confirm that you free all the memory you have allocated.
For Linux valgrind is the normal choice. There are similar memory checkers for every platform. They are all simple to use, just run your program through it.
$ valgrind ./bin/production <dat/production.txt
==3946== Memcheck, a memory error detector
==3946== Copyright (C) 2002-2015, and GNU GPL'd, by Julian Seward et al.
==3946== Using Valgrind-3.11.0 and LibVEX; rerun with -h for copyright info
==3946== Command: ./bin/production
==3946==
AA BB 4
A B
AB BA
AA CC
CC BB
A B 3
A C
B C
c B
==3946==
==3946== HEAP SUMMARY:
==3946== in use at exit: 0 bytes in 0 blocks
==3946== total heap usage: 18 allocs, 18 frees, 44 bytes allocated
==3946==
==3946== All heap blocks were freed -- no leaks are possible
==3946==
==3946== For counts of detected and suppressed errors, rerun with: -v
==3946== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
Always confirm that you have freed all memory you have allocated and that there are no memory errors.
Look things over and let me know if you have further questions.

Can't run printf() on a null-terminated string

printf() throws a segmentation fault when I pass a null-terminated string for some reason.
Here's a demonstration of my problem in GDB
λ sudo gdb -q notesearch
Reading symbols from notesearch...done.
(gdb) break 53
Breakpoint 1 at 0x400b32: file notesearch.c, line 53.
(gdb) run
Starting program: /home/frosty/hack/chapter_2/code/notesearch
[DEBUG] UserID: 0
[DEBUG] File Descriptor: 3
Breakpoint 1, print_notes (fd=3, uid=0, searchstring=0x7fff3daf7fc0 "")
at notesearch.c:53
53 printf("%s\n", note_buffer);
(gdb) x/8xb note_buffer
0x7feb5a997168: 0x68 0x65 0x6c 0x6c 0x6f 0x0a 0x00 0x00
(gdb) x/s note_buffer
0x7feb5a997168: "hello\n"
(gdb) next
Program received signal SIGSEGV, Segmentation fault.
_dl_fixup (l=, reloc_arg=)
at ../elf/dl-runtime.c:148
148 ../elf/dl-runtime.c: No such file or directory.
(gdb)
Here's the source code around the problem
int print_notes(int fd, int uid, char *searchstring){
int note_length = find_user_note(fd, uid);
if (note_length == -1)
return 0; // End of file
char* note_buffer;
read(fd, note_buffer, note_length);
note_buffer[note_length] = 0; // null terminator byte
if(search_note(note_buffer, searchstring)) {
printf("%s\n", note_buffer);
}
return 1;
}
remember that in C, arrays are indexed from 0 through (length of array-1)
This line:
char* note_buffer;
declares an initialized pointer to character. I.E. its value depends on what ever trash is currently in memory at that location. Such an action as accessing where that trash 'points' would be undefined behavior and can lead to a seg fault event.
Strongly suggest, after this line:
char* note_buffer;
inserting the following: (including the checking for a malloc() failure:
note_buffer = malloc( note_length+1 );
if( !note_buffer )
{
perror( "malloc failed" );
exit( EXIT_FAILURE );
}
// implied else, malloc successful
Note: without the +1 on the call to malloc() the following line:
note_buffer[note_length] = 0;
would be setting a byte that is one past the end of the allocated area. That would be undefined behavior and can lead to a seg fault event
Also, a 0 has the bit pattern 0x000000000000000000000000 and a '\0' has the bit pattern 0x00000000. the implicit conversion feature will save you in this instance, but do not rely on that feature, instead properly code literals. so the line should be:
note_buffer[note_length] = '\0';
Note: perror() outputs the enclosed text string AND the reason the OS thinks the error occurred to stderr, which is where all error messages should be output.
Null terminator is indicated by \0 not 0
note_buffer[note_length] = 0;
should be
note_buffer[note_length] = '\0';

search in text file [duplicate]

I'm trying to create a code, which reads from textile, and then stores the data into memory, prints out to the screen so the user can read it, but it is still saved into the memory so you can use it for the rest of the program..
Here is the sample of the textile
75
nevermind
nvm
not much
nm
no problem
np
people
ppl
talk to you later
ttyl
because
cuz
i don't know
idk
as soon as possible
asap
yeah
ya
how are you
hru
you
the list goes on, it has a total of 150 words, 151 lines if the first number is included. The 75 serves to tell you how many pairs there are.
anyways, here is the code that i Have written so far, it uses this struct
typedef struct
{
char *English;
char *TextSpeak;
}Pair;
The code i have written so far is:
FILE *infile =fopen("dictionary.txt","r");
int phraseCounter;
fscanf(infile, "%i", &phraseCounter); //Now you have the number of phrase pairs
//Allocate memory
Pair *phrases=malloc(sizeof(Pair) * phraseCounter);
//Run loop
for(int i=0; i < phraseCounter; i++){
//Get the english word
phrases[i].English = malloc(sizeof(char));
fscanf(infile,"%s",phrases[i].English);
//run loop to read next line
for(int a=0; a < phraseCounter; a++){
phrases[i].TextSpeak = malloc(sizeof(char));
fscanf(infile,"%s",phrases[i].TextSpeak);
}
printf("%s - %s\n", phrases[i].English, phrases[i].TextSpeak);
}
fclose(infile);
for(int i=0; i < phraseCounter; i++)
free(phrases[i].English);
free(phrases);
The output i keep getting is:
nevermind - atm
by - definitely
def -
-
-
-
-
-
And it keeps going for 75 lines.
Now I'm not sure whether I should use a 2D array or if this will be acceptable. Any help will be appreciated! Thanks
phrases[i].English = malloc(sizeof(char));
Here the problem lies, you are allocating a single byte and then trying to cram a string into it, which leads to undefined behavior here:
fscanf(infile,"%s", phrases[i].English);
Generally, you should assume a sensible buffer length and read that, and check whether the new line is contained. If that's not the case, read again into another buffer or enlarge the old one (using realloc).
Either that or use a non-standard function like getline that does this already for you under the hood.
Given that your lines are pretty short sentences, a constant buffer size could suffice (let's call it MAX_LINE), which provides us a little easier way to achieve the same:
fscanf(infile, "%*[^\n]s", MAX_LINE, buf);
This reads a string of length MAX_LINE into the buffer buf and terminates before the '\n' is encountered.
When reading strings, you should refrain from using fscanf("%s", buf) and use fgets() or scanf("%*s", MAX_LINE, ...) instead. This ensures that there will be no attempt to write more data than what you specified, avoiding buffer overflows.
Edit: The nested loop shouldn't be there. You are basically overwriting phrases[i].TextSpeak a total of phraseCounter times for no benefit. And in the process of that you are leaking a lot of memory.
There are a number of ways to do this. However, one suggestion I would have would be to make use of line-input tools such as fgets or getline to make reading the file more robust. It is fine to use fscanf for discrete variables (I left it for reading phraseCounter), but for reading string data of unknown length/content, line-input really should be used.
Below is an example of your code with this employed. The code is commented to explain the logic. The real logic here is the fact that you will read 2-lines for each allocated struct. A simple line counter using % (mod) as a toggle can help you keep track of when to allocate a new struct. I also added code to accept the filename as the first argument to the program. (to run, e.g ./progname <filename>). Let me know if you have questions:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAXL 128
typedef struct Pair
{
char *English;
char *TextSpeak;
} Pair;
int main (int argc, char** argv) {
if (argc < 2) {
fprintf (stderr, "error: insufficient input. Usage: %s filename\n", argv[0]);
return 1;
}
Pair **pair = NULL; /* pointer to array of pointers */
char line[MAXL] = {0}; /* variable to hold line read */
FILE* infile = NULL; /* file pointer for infile */
unsigned int phraseCounter = 0; /* count of pairs */
unsigned int index = 0; /* index to pairs read */
size_t nchr = 0; /* length of line read */
size_t lnum = 0; /* line number read */
/* open file and validate */
if (!(infile = fopen ((argv[1]), "r"))) {
fprintf (stderr, "error: file open failed '%s'.\n", argv[1]);
return 1;
}
/* read phraseCounter */
if (!fscanf (infile, "%u%*c", &phraseCounter)) {
fprintf (stderr, "error: failed to read phraseCounter.\n");
return 1;
}
/* allocate phraseCounter number of pointers to Pair */
if (!(pair = calloc (phraseCounter, sizeof *pair))) {
fprintf (stderr, "error: memory allocation failed.\n");
return 1;
}
/* read each line in file */
while (fgets (line, MAXL - 1, infile) != NULL)
{
nchr = strlen (line); /* get the length of line */
if (nchr < 1) /* if blank or short line, skip */
continue;
if (line[nchr-1] == '\n') /* strip newline from end */
line[--nchr] = 0;
if (lnum % 2 == 0) /* even/odd test for pair index */
{
/* allocate space for pair[index] */
if (!(pair[index] = calloc (1, sizeof **pair))) {
fprintf (stderr, "error: memory allocation failed for pair[%u].\n", index);
return 1;
}
pair[index]-> English = strdup (line); /* allocate space/copy to English */
}
else
{
pair[index]-> TextSpeak = strdup (line);/* allocate space/copy to TextSpeak */
index++; /* only update index after TextSpeak read */
}
lnum++; /* increment line number */
}
if (infile) fclose (infile); /* close file pointer after read */
/* print the pairs */
printf ("\n Struct English TextSpeak\n\n");
for (nchr = 0; nchr < index; nchr++)
printf (" pair[%3zu] %-24s %s\n", nchr, pair[nchr]-> English, pair[nchr]-> TextSpeak);
/* free memory allocated to pair */
for (nchr = 0; nchr < index; nchr++)
{
if (pair[nchr]-> English) free (pair[nchr]-> English);
if (pair[nchr]-> TextSpeak) free (pair[nchr]-> TextSpeak);
if (pair[nchr]) free (pair[nchr]);
}
if (pair) free (pair);
return 0;
}
Input
$ cat dat/pairs.txt
10
nevermind
nvm
not much
nm
no problem
np
people
ppl
talk to you later
ttyl
because
cuz
i don't know
idk
as soon as possible
asap
yeah
ya
how are you
hru
Output
$ ./bin/struct_rd_pairs dat/pairs.txt
Struct English TextSpeak
pair[ 0] nevermind nvm
pair[ 1] not much nm
pair[ 2] no problem np
pair[ 3] people ppl
pair[ 4] talk to you later ttyl
pair[ 5] because cuz
pair[ 6] i don't know idk
pair[ 7] as soon as possible asap
pair[ 8] yeah ya
pair[ 9] how are you hru
Verify no memory leaks
$ valgrind ./bin/struct_rd_pairs dat/pairs.txt
==3562== Memcheck, a memory error detector
==3562== Copyright (C) 2002-2012, and GNU GPL'd, by Julian Seward et al.
==3562== Using Valgrind-3.8.1 and LibVEX; rerun with -h for copyright info
==3562== Command: ./bin/struct_rd_pairs dat/pairs.txt
==3562==
<snip>
==3562==
==3562== HEAP SUMMARY:
==3562== in use at exit: 0 bytes in 0 blocks
==3562== total heap usage: 32 allocs, 32 frees, 960 bytes allocated
==3562==
==3562== All heap blocks were freed -- no leaks are possible
==3562==
==3562== For counts of detected and suppressed errors, rerun with: -v
==3562== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 2 from 2)

Resources