Xcode debugger messing with input - c

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?

Related

Access to argv[1] blocks the program

I'm trying to get an ip address from the command line, so I prepared a simple parser. The problem is that the program seems to stop when I try to read from argv[i].
int main(int argc, char * argv[]){
unsigned char packet[1500];
int n,len,i,j;
unsigned char dstmac[6];
unsigned char targetip[4];
unsigned char * add;
unsigned char byte=0;
if(argc==2){
j=0;
i=0;
add = argv[1];
printf(">>%s<< \n",add);
fflush(stdout);
printf("%c ",add[1]);
fflush(stdout);
while(add[i]) {
printf("%c ",add[i]);
fflush(stdout);
if( add[i] != '.' )
byte = byte*10+(add[i]-48);
else{
targetip[j++] = byte;
byte=0;
}
i++;
}
targetip[j++]=byte;
}
else{
targetip[0]=88;
targetip[1]=80;
targetip[2]=187;
targetip[3]=50;
}
printf("TARGET IP: %d.%d.%d.%d",targetip[0],targetip[1],targetip[2],targetip[3]);
fflush(stdout);
struct eth_frame * eth;
struct ip_datagram * ip;
struct icmp_packet * icmp;
//etc.....
I really don't know why. Can you help me?
EDIT: update code with fflush(stdout)
ACTUAL OUTPUT:
1238166#localhost:~/ping$ gcc ping2.c -o np
1238166#localhost:~/ping$ ./np 216.58.205.67
>>216.58.205.67<<
1
2 1 6 . 5 8 . 2 0 5 . 6 7 TARGET IP: 216.58.205.67
now the programm blocks when it prints the "TARGET IP".
In the rest of the programm there is the pakcet initialization and exchange. I have already tested this part and it should work.
UPDATE: what I noticed is that the program now needs an ffflush(stdout) to go on, but before this was not necessary. If I run for example without arguments (the else clause), all works properly.
1238166#localhost:~/ping$ ./np
TARGET IP: 88.80.187.50destmac: f2(242) 3c(060) 91(145) 2c(044)
53(083) b7(183)
================
SENT PACKET:
f2(242) 3c(060) 91(145) 2c(044)
53(083) b7(183) ....
When I tried your program, it didn’t block. The program terminates.
However, the instructions printf("%c ",add[1]); and printf("%c ",add[i]); had no visible effect. This is because the character is buffered and not printed to the console. The buffered content is out put to the console when a fflush(stdout); is performed. Printf does this itself when there is a \n in the output string. The buffer content is also output to the console when the program terminates on Linux.
When I run your program with the argument 123.45.67.255, I get the single line output 2 1 2 3 . 4 5 . 6 7 . 2 5 5 TARGET IP: 123.45.67.255 which is what it is supposed to be.
The output you see is Windows specific.Apparently, on Windows the buffer content is not flushed when the program terminates. You must add a \n at the end of the format string of the last printf.
Note: modifying the question after the question is answered make the answer confusing.

Stack smashing while casting and copying from one buffer to another

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.

Double Ctrl+D input when using scanf for strings on Windows

Here's the situation, I have a code that reads values until the user inputs Ctrl+D, the problem though is I have to input it TWICE for it to successfully exit the loop, I figured it had to do with the fact that the Ctrl+D was being inserted into the string along with the remainings of the buffer and therefore didn't register as EOF and simply another character inside the string and only the second Ctrl+D which would be saved in an int variable, actually stopped the reading loop. To solve this I added while(getchar() != '\n') to see if it fixed the problem, but to no end.
Here's my code:
typedef struct {
char nome[50];
int tempo;
int ncertas;
} equipa;
int ler_equipas(equipa *resultados)
{
int x, r1, r2 ,r3 ,r4, r11, r22, r33 ,r44, rcertas = 0, i = 0;
scanf ("%d %d %d %d", &r1, &r2, &r3, &r4);
while (scanf ("%s %d %d %d %d %d", resultados[i].nome, &resultados[i].tempo, &r11, &r22, &r33, &r44 ) == 6 )
{
i++;
if (r1 == r11) rcertas++;
if (r2 == r22) rcertas++;
if (r3 == r33) rcertas++;
if (r4 == r44) rcertas++;
resultados[i-1].ncertas = rcertas;
rcertas = 0;
while((x=getchar()) != '\n');
}
return i;
}
The input/output was as follows (">>" means output):
1 2 3 4
>> correct answers are 1 2 3 4
Team1 234 1 2 3 4
>> values inputed for team time and answers: Team1 234 1 2 3 4
>> getchar value was (ASCII): 10
>> Next read:
Team2 400 1 3 2 4
>> values inputed for team time and answers: Team2 400 1 3 2 4
>> getchar value was (ASCII): 10
>> Next read:
>>
^D
^D
>> return i was reached
>> Number of teams: 2
>> Team "Team1" took 234 seconds and answered 4 questions correctly
>> Team "Team2" took 400 seconds and answered 2 questions correctly
Since you are using windows, you shall use ctrl+z for emulating EOF
See https://stackoverflow.com/a/16136924/4386427
When you use ctrl+d, the first ctrl+d matches the initial %s so the scan continues.
The second ctrl+d will not match %d so the scan terminates. Since the number of scanned elements isn't 6, the while loop terminates.
Consequently two ctrl+d terminates the function. A single ctrl+z will also terminate the program.
I did not try this yet. But i remember having the same Problems...
Try this: How to clear input buffer in C?
while ((c = getchar()) != '\n' && c != EOF) { }
This is a way to clear the input buffer. But this after a scanf(); call to clear the input Buffer.
Best regards

fgetc dropping characters when reading 2d pixel map with for loop

I am working on inputting a 2d pixel array from a PPM file with the one I am testing being of width and length 5. Also I am aware that in a ppm file that is rgb it has 3 color values not just one. I had forgotten that before I wrote this code, but the problem still persists even with the update to it and the problem still exists in the same way. I have simplified the problem to just the array as to isolate the problem. From what I can tell this seems to be both dropping characters and replacing some with new line characters as well. Any insight into why this is happening would be greatly appreciated and if I forgot to add something I will update this as soon as I am aware.
#include <stdio.h>
int main(int args, char *argv[]) {
int w = 5, h = 5;
FILE *f = fopen(argv[1], "rb");
int c = 'a';//I am setting this so as to avoid the off chance of c being defined as EOF
for(int i = 0; i < h && c != EOF; i++) {
for(int j = 0; j < w && (c = fgetc(f)) != EOF; j++) printf("%c", c);
fgetc(f);//To remove the '\n' character I am not using fgets because it stops at '\n' character and it is possible for a rgb value to be == to '\n'
printf("\n");
}
fclose(f);
return 0;
}
Test File I am using:
12345
abcde
12345
abcde
12345
Output I am getting:
12345
abcd
123
5
ab
de
1
Thanks in advance!
Edit: This is running on the windows 10 command prompt
The problem is that '\n' on a Windows machine actually ends up producing two characters, a carriage return (ASCII code 13) and a line feed (ASCII code 10). When you open a file in binary mode, those line endings are not translated back to a single character. You're only accounting for one of these characters, so you're getting off by a character on each line you read.
To illustrate this, replace your printf("%c", c);" with printf("%d ", c);. I get the following output:
49 50 51 52 53
10 97 98 99 100
13 10 49 50 51
53 13 10 97 98
100 101 13 10 49
You can see those 10s and 13s shifting through.
Now try adding a second fgetc(f); to eat the line feed and it will work much better. Keep in mind, however, that this only works on files with CRLF line endings. Port it to Linux or Mac and you will have more troubles.

Reading and Writing Files in C using read(...) write(...)

These commands are supposed to return bytes read or written.
Currently, I am trying to read and write 100 characters at a time.
When I use read(fd, buffer, 100) I get 99 characters read. When I use read(fd, buffer, 101) I get 100 characters read. What is the problem?
I am supposed to read 100 characters from a source code and write them to a destination1. Then, I am supposed to read 50 characters from same source into destination2.
The reading and passing is inaccurate after the first few loops. Problems arise on the third loop.
Please check it out:
[Step 2] Prcs_P2.c: Copy the contents of source.txt into destination1.txt and
destination2.txt as per the following procedure.
1. Read the next 100 characters from source.txt, and among characters read,
replace each character ’1’ with character ’A’ and all characters are then
written in destination1.txt
2. Then the next 50 characters are read from source.txt, and among characters
read, replace each character ’2’ with character ’B’ and all characters are
then written in destination2.txt
3. The previous steps are repeated until the end of file source.txt.
The last read may not have 100 or 50 characters.
-------------
It's copying characters irregularly. sometimes more than 100 | 50 and sometimes less.
int main() {
//const int sizeBuff=100;
char buffer[105]; //used to carry information in packets of 10
int temp=0; //temp variable to check for errors
int charCount=0;
int i=0;
//----------------------------------------
//charCount=read(sourceFile, buffer , 101 );
while( charCount=read(sourceFile, buffer , 100) >0){ //needed 101 as last arg instead of 100. DUnno why?
i=0;
while(i<charCount){
if (buffer[i]=='1')
buffer[i]='A';
i++;
}
if(write( destinationFile, buffer,charCount)==-1) //write(...) returns the number of bytes written to destinationFile
//-1 depicts error in the function and 0 is returned upon end of file
{
printf("\nWrite fail.\n");
perror("Error"); //Prints error, if found while writing.
}
memset(buffer, 0, 105); //CLEARS BUFFER
i=0;
charCount=read(sourceFile, buffer , 50 ); //reads 50 bytes at a time //need flag for error
while(i<charCount){
if (buffer[i]=='2')
buffer[i]='B';
i++;
}
temp=write( destinationFile2, buffer, charCount); //write(...) returns the number of bytes written to destinationFile
if(temp==-1) //-1 depicts error in the function and 0 is returned upon end of file
{
printf("\nWrite fail.\n");
perror("Error"); //Prints error, if found while writing.
}
memset(buffer, 0, 105);
}//while loop ends
close(destinationFile);
close(destinationFile2);
close(sourceFile);
//------PART 1 ENDS-------------
//------PART 2 STARTS------------
}
charCount=read(sourceFile, buffer , 100) >0
This sets charCount to 0 or 1. You want
(charCount = read(sourceFile, buffer , 100)) > 0

Resources