C write() function sending 2 bytes hexadecimal - c

I'm working with TCP sockets. I'm sending data to the open socket using the write function.
write(Socket_Fd, "test", 4);
That works. But when I do it this way.
#include <stdio.h>
#include <stdlib.h>
typedef unsigned char BYTE;
typedef struct LANC
{
BYTE START;
BYTE END;
} LCODE;
int main(int argc, char *argv[]){
LCODE COMMAND;
COMMAND.START = 0x28;
COMMAND.END = 0x06;
short value = (COMMAND.START << 8) | COMMAND.END;
write(socket_FD, value, sizeof(value);
return 0;
}
when I check the size of the value I get 2 bytes which is correct since i combined 0x28 and 0x06. So doing a printf.
printf("%x\n", value);
output is: 2806 which is correct.
printf("%d\n", sizeof(value);
output is: 2 bytes which is correct.
I'm getting an error when I'm trying to write the hexadecimal to the open socket using write. What am I doing wrong?

You're committing two disgusting errors in one line (how does it even compile?). You're passing an integer (value) to write() where it expects a pointer (that won't compile, you're trying to deceive us about your code). Secondly, you're doing something that's endian-dependant, that is, on different processors you'll get different results depending on whether the high-byte of "value" comes first or second in memory.
Solution:
unsigned char value[2] = {COMMAND.START, COMMAND.END};
write(socket_FD, value, sizeof(value));

Related

Reading 23 bytes even the buffer is of 10bytes

I know it's very dumb but I really don't get what the heck is happening here.
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
int getinput()
{
char buf[10];
int rv = read(0, buf, 1000);
printf("\nNumber of bytes read are %d\n", rv);
return 0;
}
int main()
{
getinput();
return 0;
}
I can't understand how this read() function is working.
read(0, buf, 1000)
Also, the buf is 10 bytes long why it is taking 23 bytes?
Array-pointer equivalence
In C, an array like the variable buf in your example is just a pointer to the memory address of the first allocated byte.
You can print the value of this pointer:
#include <stdio.h>
int main(void) {
char buf[10];
printf("Address of the first byte of buf: %p\n", buf);
return 0;
}
Output:
Address of the first byte of buf: 0x7ffd3699bfb6
Pointer arithmetic
When you write something into this buffer with an instruction like
buf[3] = 'Z';
It is in fact translated to
*(buf+3) = 'Z';
It means "add 3 to the value of the pointer buf and store the character 'Z' at the resulting address".
Nothing is stopping you from storing the character 'Z' at any given address. You can store it before or after the address pointed to by buf without any restriction. If the address you choose happen to be the address of another variable, it cannot produce a segmentation fault (the address is valid).
In C, you can even write the character 'Z' at the address 123456 if you like:
int main(void) {
char *address = (char *)123456;
*address = 'Z';
return 0;
}
The fact that your buffer is 10 bytes long does not change that. You cannot "fix" this because writing anything at any memory location is a fundamental feature of the C programming language. The only "fix" I can think of would be to use another language.
File descriptors opened at program startup
In your exemple, you pass the value 0 as the first argument of the function read(). It seems that this value corresponds to the file descriptor of the standard input. This file descriptor is automatically opened at program startup (normally you get such a file descriptor as the result of a call to the function open()). So, if you get 23 read bytes, it means that you typed in 23 characters on your keyboard during the program execution (for instance, 22 letters and 1 newline character).
It would be better to use the macro name of the standard input file descriptor:
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
int getinput()
{
char buf[10];
int rv = read(STDIN_FILENO, buf, 10);
printf("\nNumber of bytes read are %d\n", rv);
return 0;
}
int main()
{
getinput();
return 0;
}
your sample is a perfect example of a buffer overflow.
read(0, buff, 1000) will most probably corrupt the memory (stack on your case).
Read will take the start address of your buf pointer and will write those 23 bytes in your case... if there are some other structures on the memory they will be overwritten by those 13 bytes and can lead to very unwanted behavior (maybe even crashes of you application)
C gives the responsibility to handle memory correctly to the programmer. So there is no bounds checking.
You call read() with 3 arguments:
The file handle, in your case "0".
The pointer to the array of bytes to fill with the bytes read from the file, in your case buf.
The size of this array, in your case "1000".
Apparently the file has only 23 bytes, which is less or equal to 1000, so read() returns this value.
Note: But before, it happily wrote all these 23 bytes into the array. Since your buffer has just a capacity of 10 bytes, the memory after it gets overwritten. This is called "buffer overflow" and is a common error, abused for evil attacks, or possibly leading to crashes or malfunction (Thanks, ikegami!).
To fix this error, I recommend to change the read into:
read(0, buf, sizeof buf);
This way your are always giving the right size to read(). (If you declare buf as an array, of course.)

Writing a struct to a buffer

I am trying to understand the process by which I can serialize and de-serialize data in C. I wrote code that I believe should write a simple struct to a char buffer.
#include <packet.h>
#include <stdio.h>
#include <string.h>
#include <stdint.h>
typedef struct
{
int A;
int B;
int C;
}test_packet;
int main(int argc, char** argv)
{
test_packet p;
p.A = 1;
p.B = 2;
p.C = 3;
char buffer [sizeof(p)];
memcpy(buffer, &p, sizeof(p));
printf("%x \n", buffer);
return 0;
}
However, when I run this code, since the struct being serialized is statically coded, I expect to see a buffer that's the same each time. I don't, I see a buffer that appears to be full of random data:
./SerializePacket
41bf5380
./SerializePacket
d89fc790
./SerializePacket
aea2c00
./SerializePacket
d355dc10
Can anyone alleviate me of my ignorance here?
What you are printing is a pointer, the address of the buffer.
About serialization: you are copying the struct over the buffer, with padding and all. That it's not portable, unless you serialize and de-serialize in the same computer. To serialize a struct directly copying to the buffer, you should use packed structures (see: What is a "packed" structure in C?, https://en.wikipedia.org/wiki/Data_structure_alignment). Also, using an integer of fixed size is preferred for serialized data, for example, uint16_t for a 16 bits unsigned integer.

Which placeholder for fscanf?

I have a file that I open which has a bunch of lines with data like this:
0x804ae1c: W 0x0000000c
I'm trying to extract the 3 different strings into 3 different variables but I'm having problems getting values from the 2nd and third token.
Here is how I'm trying to do it:
unsigned long address;
unsigned long address2;
char* readWrite;
fscanf(traceFile, "%lx %s %lx\n", &address, line, &address2)
I get the pointer for the first line. i.e:
804ae1c
but after that the other 2 variables do not get the proper things assigned to them. I tried changing line to a char but to no avail. How should I proceed fixing this issue?
Thanks!
First, you need to allocate storage, rather than just declaring a char*. If you are reading only a single character, a simple char is sufficient.
As BLUEPIXY's comment mentions, you need to account for the extra : character in your string. Here is a test program that shows this (reads from stdin).
#include <stdio.h>
int main(){
unsigned long address;
unsigned long address2;
char readWrite;
int retVal;
retVal = scanf("%lx: %c %lx", &address, &readWrite, &address2);
if (retVal == 3) {
printf("%lu: %lu %c\n", address, address2, readWrite);
} else {
fprintf(stderr, "Parsing error\n");
}
}

Segmentation fault in reading a .dat file

Right now, I'm working on an example code that I wish to integrate into my program later. What essentially I'm trying to do is read a .dat file byte by byte and interpret the data (ie. interpret boot sector to output the sector size, reserved sectors etc.)
To do this, I am reading the data byte by byte and, using the descriptions in fat12 of https://www.win.tue.nl/~aeb/linux/fs/fat/fat-1.html#ss1.3 , I translate the data into the information that I want. Right now, I can pull individual bytes from the file (Is it right to assume that the data pulled is in hex?). However, I need two bytes to have something meaningful. So, I need to combine two bytes into one, convert the hex data into decimal and output the information. Unfortunately, right now, I'm getting a seg fault and for the life of me, I can't figure out what's wrong. Thanks in advance!
int main (int argc, char **argv){
FILE *fp ,*fptest;
long lSize;
char *buffer;
//Open file
fptest= open("fat_volume.dat", "rb");
//Read file into buffer
fread(buffer,1,512,fptest);
//Parse the boot sector
char tmpA, tmpB;
tmpA = buffer[10]; //First byte
tmpB = buffer[11]; //Second byte
//Combine the two bytes into one
char combinedBytes[3];
strcpy (combinedBytes, tmpA);
strcat (combinedBytes, tmpB);
//Hex to decimal converter
long int li1;
li1 = strtol (combinedBytes,NULL,16);
printf ("The sector size is: %ld.\n", li1);
return 0;
}
You must allocate buffer; e.g.
char buffer[512];
or
char *buffer = malloc(512);
EDIT:
The string operations
strcpy (combinedBytes, tmpA);
strcat (combinedBytes, tmpB);
do not make sense either and access/copy too much data (the compiler will warn you about this!).
I suggest do read values as
unsigned char tmpA = buffer[10];
unsigned char tmpB = buffer[11];
unsigned int tmp = (tmpA << 8) | (tmpB << 0); /* or revert in in case of
little-endian */
To make things more efficient, I would write it as
struct fat_header {
uint8_t pad0[10];
uint16_t my_val;
uint8_t pad1[500];
} __attribute__((__packed__)); /* this is not portable and for gcc! */
...
struct fat_header hdr;
fread(&hdr, 1, sizeof hdr, f);
uint16_t val = be16toh(hdr.my_val); /* or le16toh() in case of le */
You are reading into a buffer you never allocated memory for.
What you're trying now is to read from some junk value in memory, who knows, which almost always leads to a segmentation fault.
Use:
char *buffer = malloc(512 * sizeof(char)); // this allocates 512 times the size of a single char of memory
If you don't specify the number inside malloc to be of a specific size (e.g. malloc(512) the number is in bytes, though I think it's better to always include it.
This specific error is called dereferencing a null pointer
EDIT:
I've managed to run this code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main (int argc, char **argv)
{
FILE *fp ,*fptest;
long lSize;
char *buffer;
//Open file
fptest = fopen("input.txt", "rb");
if (fptest == NULL)
{
printf("Error occurred when opening file");
return 1;
}
buffer = malloc(sizeof(char) * 512);
//Read file into buffer
fread(buffer,1,512,fptest);
//Parse the boot sector
char tmpA, tmpB;
tmpA = buffer[10]; //First byte
tmpB = buffer[11]; //Second byte
//Combine the two bytes into one
char combinedBytes[3];
strcpy (combinedBytes, &tmpA);
strcat (combinedBytes, &tmpB);
//Hex to decimal converter
long int li1;
li1 = strtol (combinedBytes,NULL,16);
printf ("The sector size is: %ld.\n", li1);
return 0;
}
You also used a function open() which must be fopen(), and you need to pass the address of tmpA and tmpB to strcpy and strcat.
This is why I don't understand why your compiler doesn't give any errors or warnings..

How to read from char buffer into unsigned long and short

Edit: I am not sure if this code does what I think it does. Could someone tell me how to test it? I.e. what should the buffer in my main function look like? I am assuming that a buffer has data of two fields in the following order type(16 bits), length(32 bits). I'm assuming that the buffer is read in from a file and each of the fields is separated by a space. The fields are stored in network byte order and when I read them I have to convert them back to host byte order.
I'm expecting that the code will read the contents from the file (which should be in network byte order) and display the contents in host byte order. I'm a bit confused about type conversions and what the network byte order will be inside of a file, so I don't know what values to use to test it. Also, I'm not sure if my code is written correctly, could someone who does this sort of thing or knows a bit more about such conversions tell me if my code is correct?
Here's the code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void printRecords(char *buffer)
{
unsigned int recordType;
unsigned long recordLength;
char *data;
char *index;
if (!buffer)
printf("Empty buffer\n");
while(*buffer)
{
memcpy(&recordType,(const void *) buffer,2);
buffer += 3;
recordType = ntohs(recordType);
printf("Record type normal: %u\n",recordType);
memcpy(&recordLength,(const void *) buffer,4);
buffer += 5;
recordLength = ntohl(recordLength);
printf("Record Length normal: %l\n",recordLength);
break;
}
}
void main()
{
char * buffer = "0000000000000001 00000000000000000000000000000001";
printRecords(buffer);
}
char *buffer = malloc(sizeof(buf));
sizeof means "size of buf's type", ie the size of a pointer to char; you probably want
malloc(strlen(buf) + 1); /* 1 for trailing '\0' */
Then you are mistaking the value of the bytes for their conversion to string:
"256" is byte '2' followed by byte '5' and '6' -- '2' is not equals to 2, '5' is not equals to 5 etc.
The 256 you are talking about is 00000001 00000000 instead (try dumping the bytes to stdout and you'll see).
Also, recordType should be of type uint16_t, not unsigned -- you're never too paranoid.
EDIT: atoi takes a pointer to char, as in
atoi("123")
not a pointer to int!

Resources