overflow when using uint32_t - c

#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
char* createMSG(uint8_t i,uint32_t port);
int strlen(char* tmp);
uint32_t user_port = 5000;
int main(int argc, char** argv) {
char *msg;
uint8_t i;
i = 1;
msg = createMSG(i,user_port);
printf("Port: %d",*(msg+2));
}
char* createMSG(uint8_t i,uint32_t port) {
char *buff;
buff = (char*) malloc(6);
uint8_t id;
id = 2;
memcpy(buff, &id, sizeof(uint8_t));
memcpy(buff+1, &i, sizeof(uint8_t));
memcpy(buff+2, &port, sizeof(uint32_t));
return buff;
}
The output is: "Port: -120". It seems there is some overflow. But uint32_t should be big enough for 5000. When using 22 instead of 5000, everything is ok.
Why?

Because *(msg+2) has type char. If you really want to do that, you should do
printf("Port: %d",*(uint32_t*)(msg+2));
As noted by #R.., msg+2 almost certainly does not meet the right alignment requirements for type uint32_t. If the code appears to work, it's an accident and not portable.

This line
printf("Port: %d",*(msg+2));
prints the 'char' value at (msg+2) address, not the uint32_t !
Use
uint32_t PortFromProc = *(uint32_t*)(msg+2);
printf("Port: %d", PortFromProc);
To "fix" port numbers from recvfrom() function one must use the ntohl() function.

Related

Why Converting command char double pointer to char is not working in case of command line argument?

Here is the code
#include <stdio.h>
//#include "ConvertEndianess.h"
typedef unsigned char uint8_t;
void ConvertEndianess(uint8_t* buffAddr, uint8_t length);
void ConvertEndianess(uint8_t *buffAddr, uint8_t length)
{
uint8_t i;
uint8_t data;
for (i = 0U; i < (length / 2U); i++)
{
data = buffAddr[i];
buffAddr[i] = buffAddr[(length - 1U) - i];
buffAddr[(length - 1U) - i] = data;
}
}
int main(int argc, char *argv[]){
printf("\nNumber Of Arguments Passed: %d\n",argc);
if(argc < 3){
printf("Too Few Arguments\n");
}
else if(argc > 3){
printf("Too Many Arguments\n");
}
else{
printf("data indianess: %s\n",argv[1]);
ConvertEndianess((uint8_t *)&argv[1], (uint8_t)(*argv[2]));
printf("data indianess: %s\n",argv[1]);
}
}
Here is my argument:
./a 11223344 4
It is printing correctly before going to conversion API but maybe some casting mistake is done by me and I'm not able to identify it.
Can anyone please correct my mistake with explanation?
(uint8_t)(*argv[2])
argv[2] is a char * and according to how your program operates, I assume that is supposed to contain the size of the buffer. Since this is a string (char *), and you want to convert it to a number, you'll need to use sscanf to get this value:
Sample useage:
size_t len;
sscanf(str, "%zu", &len);
Then pass len as the second argument of your conversion function.
The way you are doing it presently passes the ASCII code for the first character of argv[2]. So if the user said the size is "7" you are actually passing the integer 55 to the conversion function.
As a side note, use size_t to represent size, not uint8_t.
The main problem on your code is that you cast &argv[...] with an incompatible type.
argv[...] is a char* so &argv[...] is some char**, and you cast it as a uint8_t* which is incompatible.
Some remarks:
You should not type & before argv[...]:
You can use strlen() instead of passing an argument
You can use strtol() to convert a string into an integer
Indianness or Endianness?
#include <stdio.h>
#include <string.h> /* strlen */
#include <stdlib.h> /* strtol */
typedef unsigned char uint8_t;
void ConvertEndianess(uint8_t *buffAddr, uint8_t length)
{
uint8_t i;
uint8_t data;
for (i = 0U; i < (length / 2U); i++)
{
data = buffAddr[i];
buffAddr[i] = buffAddr[(length - 1U) - i];
buffAddr[(length - 1U) - i] = data;
}
}
int main(int argc, char *argv[]){
printf("\nNumber Of Arguments Passed: %d\n",argc);
if(argc == 2){
/* exemple with strlen */
printf("data Endianess: %s\n",argv[1]);
ConvertEndianess(argv[1], strlen(argv[1]));
printf("data Endianess: %s\n",argv[1]);
}
else if(argc == 3){
/* exemple with strtol */
printf("data Endianess: %s\n",argv[1]);
ConvertEndianess((uint8_t *)argv[1], strtol(argv[2], NULL, 0));
printf("data Endianess: %s\n",argv[1]);
}
}

Linux sscanf function doesn't fill variable

I am currently writing an FTP server and I need to parse the ip and port of a remote server from an input string buffer in the following format:
xxx,xxx,xxx,xxx,yyy,zzz
where:
xxx stands for an ip address octet in decimal
yyy is round((remote port number) / 256)
zzz is (remote port number) % 256
For example: 127,0,0,1,123,64 means ip = 127.0.0.1 and port = 31552.
I am currently using sscanf to extract the following fields from the input string buffer:
sscanf(str, "%u,%u,%u,%u,%u,%u", ret_ip, &ip[0], &ip[1], &ip[2], &temp1, &temp2) == 6
where:
str is the input buffer
ret_ip is of type uint32_t
ip's are of type uint32_t
temp1 and temp2 are of type unsigned short int
Example code:
#include <stdio.h>
#include <netdb.h>
int main(int argc, char *argv[])
{
uint32_t ip[4];
unsigned short int temp, temp1;
if (sscanf("127,0,0,1,142,214", "%u,%u,%u,%u,%u,%u", &ip[0], &ip[1], &ip[2], &ip[3], &temp, &temp1) == 6)
{
printf("%u : %u", temp, temp1);
}
return (0);
}
My problem is that, for valid string, the value of temp1 is always 0 (zero), i.e. all the other variables are filled according to string except the temp1. I would appreciate any help.
scanf isn't as forgiving of format specifier mismatches as printf is. The specifiers need to match exactly or else you invoke undefined behavior.
For unsigned short use %hu. %u is for unsigned int.
There are no direct format specifiers for types like uint32_t. You need to use a macro from inttypes.h: "%" SCNu32.
All together:
if (sscanf(str, "%" SCNu32 ",%" SCNu32 ",%" SCNu32 ",%" SCNu32 ",%hu,%hu", ret_ip, &ip[0], &ip[1], &ip[2], &temp1, &temp2) == 6)
The followings are added to this answer compare to the available answers:
Extracting the IP address octets as unsigned char and then store them as a single IP address of size uint_32 instead of having an array of uint_32. See this post for more information.
Validating against the sscanf output.
The %hu scan code is used for reading unsigned short and the
%hhu scan code is used for reading unsigned char.
Verifying the process of IP address conversion from string to unitt_32 using inet_pton and from unitt_32 to string using inet_ntop. Read this section of Beej's networking book if you want to learn more.
and here is the code:
#include <stdio.h>
#include <stdlib.h>
#include <arpa/inet.h>
int main(int argc, char *argv[]){
unsigned char ip_octects[4] = {0, 0, 0, 0};
uint32_t ip = 0;
unsigned short r1 = 0, r2 = 0;
unsigned char *str_c = "127,0,0,1,142,214";
if(sscanf(str_c, "%hhu,%hhu,%hhu,%hhu,%hu,%hu", &ip_octects[0],
&ip_octects[1], &ip_octects[2], &ip_octects[3], &r1, &r2) == 6){
printf("Extracted ip : port: %hhu.%hhu.%hhu.%hhu:%hu:%hu\n",
ip_octects[0], ip_octects[1], ip_octects[2], ip_octects[3], r1, r2);
ip = ip_octects[0] | ip_octects[1] << 8 |
ip_octects[2] << 16 | ip_octects[3] << 24;
printf("unit32_t ip value: %zu\n", ip);
/* We're done but lets verify the results using inet_pton() and inet_ntop() */
unsigned char *str_d = "127.0.0.1";
char str[INET_ADDRSTRLEN];
struct sockaddr_in sa;
if(inet_pton(AF_INET, str_d, &(sa.sin_addr)) < 1){
perror("error: invalid input for inet_pton"); exit(1);
}
printf("inet_pton ip value: %zu\n",sa.sin_addr);
if(inet_ntop(AF_INET, &(sa.sin_addr), str, INET_ADDRSTRLEN) == NULL){
perror("error: invalid input for inet_ntop"); exit(1);
}
printf("inet_ntop str value: %s\n", str);
}
else{
perror("error: invalid input for sscanf"); exit(1);
}
return (0);
}
Followling is my code which seems to work and print correct results.
char sentence []="127,0,0,1,123,64";
uint16_t ret_ip;
uint16_t ip1, ip2, ip3;
uint16_t temp1, temp2;
sscanf(sentence, "%d,%d,%d,%d,%d,%d", &ret_ip, &ip1, &ip2, &ip3, &temp1, &temp2);
printf("%d, %d\n", temp1, temp2);

Segmentation fault around MD5 code

While I am running this md5 code, it is taking maximum 64 characters length of input at run time. Whenever I am giving more than 64 characters, it is showing
Inconsistency detected by ld.so: dl-fini.c: 205: _dl_fini: Assertion ns != 0 || i == nloaded failed!
I need to hash nearly 10kb of input (only string). Do I need to change anything in the header file? Can anyone tell me solution please?
md5.h
#ifndef HEADER_MD5_H
#define HEADER_MD5_H
#include <openssl/e_os2.h>
#include <stddef.h>
#ifdef __cplusplus
extern "C" {
#endif
#ifdef OPENSSL_NO_MD5
#error MD5 is disabled.
#endif
/*
* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
* ! MD5_LONG has to be at least 32 bits wide. If it's wider, then !
* ! MD5_LONG_LOG2 has to be defined along. !
* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
*/
#if defined(__LP64__)
#define MD5_LONG unsigned long
#elif defined(OPENSSL_SYS_CRAY) || defined(__ILP64__)
#define MD5_LONG unsigned long
#define MD5_LONG_LOG2 3
/*
* _CRAY note. I could declare short, but I have no idea what impact
* does it have on performance on none-T3E machines. I could declare
* int, but at least on C90 sizeof(int) can be chosen at compile time.
* So I've chosen long...
* <appro#fy.chalmers.se>
*/
#else
#define MD5_LONG unsigned long
#endif
#define MD5_CBLOCK 64
#define MD5_LBLOCK (MD5_CBLOCK/2)
#define MD5_DIGEST_LENGTH 16
typedef struct MD5state_st
{
MD5_LONG A,B,C,D;
MD5_LONG Nl,Nh;
MD5_LONG data[MD5_LBLOCK];
unsigned int num;
} MD5_CTX;
#ifdef OPENSSL_FIPS
int private_MD5_Init(MD5_CTX *c);
#endif
int MD5_Init(MD5_CTX *c);
int MD5_Update(MD5_CTX *c, const void *data, size_t len);
int MD5_Final(unsigned char *md, MD5_CTX *c);
unsigned char *MD5(const unsigned char *d, size_t n, unsigned char *md);
void MD5_Transform(MD5_CTX *c, const unsigned char *b);
#ifdef __cplusplus
}
#endif
#endif
md5.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "md5.h"
char *pt(char *, int );
int main(int argc, char **argv)
{
char *in;
char *out;
printf("ENter the string\n");
scanf("%[^\n]s",in);
size_t len; //unsigned long len; size_t len;
len = printf("len is %d\n",strlen(in));
out = pt(in, len);
printf("MD5 is\t: %s\n", out);
free(out);
//return 0;
}
char *pt(char *str, int length)
{
int n;
MD5_CTX c;
unsigned char digest[16];
char *output = (char*)malloc(33);
MD5_Init(&c);
MD5_Update(&c, str, length);
MD5_Final(digest, &c);
for (n = 0; n < 16; ++n)
{
sprintf(&output[n*2], "%02x", (unsigned int)digest[n]);
}
return output;
}
Problem 1
For this statement:
scanf("%[^\n]s",in);
When I compile it using the -Wall flag, I get the warning:
warning: 'in' is used uninitialized in this function [-Wuninitialized]
scanf("%[^\n]s",in);
^
As you see, in is not pointing to any location in your memory, so you first need to allocate some memory either with an array or malloc():
char in[500]; //or a higher value
char *out;
printf("Enter the string\n");
scanf("%499[^\n]s", in);
printf("\nin = .%s.\n", in);
or
char *in;
char *out;
in = malloc(500); //or a higher value
printf("Enter the string\n");
scanf("%499[^\n]s", in);
printf("\nin = .%s.\n", in);
Possible problem 2
You are assigning the return from printf() to the variable len.
len = printf("len is %d\n",strlen(in));
Return value printf:
Upon successful return, it returns the number of characters printed (excluding the null byte used to end output to strings).
Assuming you want the variable len to contain the length of the string in and not the number of characters printed by printf("len is %d\n",strlen(in)), you might want to assign the return from strlen() first:
len = strlen(in);
printf("len is %d\n", len);

Generating packets in C

I am not receiving anything in buffer. Wherever I printf my buffer, it is always empty or shows garbage value. Can anyone help?
I defined header, packet and called them in my main, but buffer still shows garbage.
#include <stdint.h>
struct header {
uint16_t f1;
uint16_t f2;
uint32_t f3;
};
struct data {
uint16_t pf1;
uint64_t pf2;
};
#include <arpa/inet.h>
#include <string.h>
#include <stdint.h>
#include "packet.h"
void htonHeader(struct header h, char buffer[8]) {
uint16_t u16;
uint32_t u32;
u16 = htons(h.f1);
memcpy(buffer+0, &u16, 2);
printf("Value of buff is: %hu\n",buffer);
u16 = htons(h.f2);
memcpy(buffer+2, &u16, 2);
u32 = htonl(h.f3);
memcpy(buffer+4, &u32, 4);
}
void htonData(struct data d, char buffer[10]) {
uint16_t u16;
uint32_t u32;
u16 = htons(d.pf1);
memcpy(buffer+0, &u16, 2);
u32 = htonl(d.pf2>>32);
memcpy(buffer+2, &u32, 4);
u32 = htonl(d.pf2);
memcpy(buffer+6,&u32, 4);
}
void HeaderData(struct header h, struct data d, char buffer[18]) {
htonHeader(h, buffer+0);
htonData(d, buffer+8);
printf("buff is: %s\n",buffer);
}
#include <stdio.h>
#include "packet.c"
#include <string.h>
#include<stdlib.h>
int main(){
struct header h;
struct data d;
char buff[18];
//printf("Packet is: %s\n",buff);
printf("Generating Packets..... \n");
h.f1=1;
d.pf1=2;
h.f2=3;
d.pf2=4;
h.f3=5;
HeaderData(h,d,buff);
strcat(buff,buff+8);
printf("Packet is: %s\n",buff);
return 0;
}
The problem is that your printf()s are either syntactically wrong (printf( "%hu", ... ); expects an unsigned short as parameter, but you pass a pointer) or you try to print buff by using "%s" but the content is binary, not text. What you could do instead was doing some kind of hexdump, like:
int i;
for( i=0; i<sizeof( buff ); i++ ) {
printf( "%x ", buff[i] & 0xff );
}
puts( "" ); // terminate the line
Please note, that using sizeof works im main() only, in the other function you've got to determine the buffer size differently.
Besides: because of the binary content of buff, you can't use strcat(). Even if you have made sure that there is a '\0' behind the last value you have copied (I haven't checked if you have), depending on the integer values you copy, there may be another '\0' value before that one and strcat() would overwrite everything form that point on.

Extended Read Sectors From Drive (INT 13h AH=42h)

I am trying to read 1 block of first hard drive into the memory. I tried with different LBAs but it loads spaces in to the buffer. In following code, i added for loop so that i can see if it loads anything else than just spaces. Do you guys know why it's only loading spaces into the buffer?
#include <stdio.h>
#include <stdlib.h>
#include <conio.h>
#include <dos.h>
#include <bios.h>
struct DAP
{
unsigned char size;
unsigned char reserved1;
unsigned char blocks;
unsigned char reserved2;
unsigned char far *buffer;
unsigned long int lbalod;
unsigned long int lbahid;
} dap;
char st[80];
unsigned char buf[512];
FILE *fptr;
unsigned long int itrations = 16450559; //10gb
unsigned long int i = 0;
void main(void)
{
clrscr();
for(; i<itrations; i++)
{
dap.size = sizeof(dap);
dap.reserved1 = 0;
dap.blocks = 1;
dap.reserved2 = 0;
dap.buffer = (unsigned char far *)MK_FP(_DS, buf);
dap.lbalod = i;
dap.lbahid = 0;
_AH = 0x42;
_DL = 0x80;
_SI = (unsigned int)&dap;
geninterrupt(0x13);
printf("%lu: %s\n", i, buf);
}
}
It's using Borland Turbo C over VMWare virtual machine that is setup with WinXP. I have also tried the same on DOSBOX on Windows 7. Any help would be much appreciated.
These are only my suggestions in the hope that they help your debugging.
Print sizeof(dap) to ensure that it is indeed 16
Insert memset(buf, 'A', sizeof(buf)); before you issue INT 13h so that you can check buf is modified or not
Try printf("%lu: [%s]\n", i, buf); instead, because when buf contains \0 around its head printf stops there. The braces should work as marks.
Print _AH and _CF which should contain return codes of INT 13h
#include <dos.h>
#include <bios.h>
struct DAP
{
unsigned char size;
unsigned char reserved1;
unsigned char blocks;
unsigned char reserved2;
unsigned char far *buffer;
unsigned long int lbalod;
unsigned long int lbahid;
} dap;
char st[50];
unsigned char buff[256];
FILE *fptr;
main(void)
{
puts ("enter the lba low double word: ");
gets (st);
dap.lbalod=atol(st);
puts ("enter the lba high double word: ");
gets (st);
dap.lbahid=atol(st);
dap.size=16;
dap.reserved1=0;
dap.blocks1;
dap.reserved2=0
dap.buffer = (unsigned char far *)MK FP(DS.buf);
_AH = 0x42;
_DL = 0x80;
_SI = (unsigned int)%dap;
geninterrupt(0x13);
puts ("enter the path: ");
gets(st);
fptr = fopen(st, "wb");
fwrite(buf,256,1,fptr);
fclose(fptr);
}
i am getting statement missing error on this line dap.buffer = (unsigned char far *)MK_FP(_DS, buf);

Resources