Convert hexidecimal char array to u8 array in C - c

Right now I have a u8 array that I successfully converted to a hexidecimal char array. Now, trying to change it back into a u8 array has been a doozy. I tried this code:
// DEMO:
char *message = "0f236a1f";
int i;
u8 final[4];
memset(final, 0, 4);
char* part = "00";
for (i = 0; i < 4; i++)
{
memcpy(part, &message[i*2], 2);
u8 num = 0;
sscanf(part, "%x", &num);
printf("%i", num);
final[i] = num;
}
I prepopulate everything with values to prevent stay memory values from messing up large portions of zeros I have in my actual data. Despite everything I have tried, occasionally the wrong values are assigned, and I can't find any other method online which does the same thing. Help me if you can, I hate C.
EDIT:
I revised my code, and am showing the real thing now, to see if it helps. The variable message is 464 zeros in a giant char * array. The console is still occasionally printing numbers besides zero, not sure why:
int i;
u8 final[232];
memset(final, 0, 232);
char part[3] = "00";
part[2] = 0;
for (i = 0; i < 232; i++)
{
memcpy(part, &message[i*2], 2);
unsigned int num = 0;
sscanf(part, "%x", &num);
printf("%i", num);
final[i] = (u8)num;
}

You are creating undefined behavior with these lines:
char* part = "00";
for (i = 0; i < 4; i++)
{
memcpy(part, &message[i*2], 2);
...
sscanf(part, "%x", &num);
part points to read only memory (this is why with strings like this we usually declare them as const char* to cause a compiler error when modification attempts occur) More info here.
You should allocate enough space for your string and null terminator with:
char part[3] = "00";

Related

Converting types resulting in bug

I got stuck in a univ project as follows:
I was doing it before I knew the format of the input, so I started reading it with %s, and it was a char[32].
Then when the project was released, I realized I needed to read the input as int.
So now I started to read it as int and now I don't want to make again all other functions I made, and they are receiving the arguments as an array of chars (char[32]).
So I made a function to convert the int value to int*, because I can't return char[32]. Hence I did, on main, a simple for to pass the values in int* to char[32]. The problem is that, when I print it on main, I see exactly the same values, but when I pass this new char[32] to my functions, I get a bug now. I guess my problem is because of '\0' or something like this.
A simple demonstration is below:
int* convert_dec_to_bin(int n){
printf("\n");
int i, j, k;
int *bits;
bits = (char*)malloc(32*sizeof(int));
for(i = 31, j = 0; i >= 0; --i){
printf("%d", n & 1 << i ? 1 : 0);
if(n & 1 << i){
bits[j] = 1;
}else{
bits[j] = 0;
}
j++;
}
printf("\n");
return bits;
}
int main(){
int i, k, instructionNameInt;
char type;
int *bits;
char bitsC[32];
//char instructionBinary[32]; I was reading like this before, ignore this line
int instructionBinary; //Now I read like this
scanf("%d", &instructionBinary);
bits = convert_dec_to_bin(instructionBinary); //This is a function where I pass the int decimal input to 32 bits in binary as int*.
//Making probably the wrong conversion here, I tried to put '\0' in the end but somehow I failed
for(k = 0; k < 32; k++){
bitsC[k] = bits[k];
}
printf("\n");
type = determine_InstructionType(bitsC);
printf("TYPE: %c\n", type);
instructionNameInt = determine_InstructionName(bitsC, type);
And several other functions...
Can someone light me up how can I fix it? I spent several hours and still didn't achieve to pass this correctly to an array of chars.

Accessing string that was passed as argument causes stack buffer overflow

I'm studying C at uni and am trying to access the string (the string representation of a binary-number) that was passed into a function to convert it into the integer-representation of that string.
Eg. "011" should return 3.
The string is the first 3 bits in a bitstream that's inputted in reverse.
char * temp_holder = (char *)malloc(sizeof(char) * 4);
int index_of_holder = 0;
for(int i = 2; i >= 0; i--){
printf("%c", buffer[i]);
temp_holder[index_of_holder] = buffer[i];
}
printf("\n");
int decimalValue = fromBinaryToInt(&temp_holder, 3);
printf("DECIMAL_VALUE: %d\n", decimalValue);
The fromBinaryToInt function is:
int fromBinaryToInt(char *string[], int length){
for(int i = 0; i < length; i++){
printf("%c", *string[i]);
}
int int_rep = strtol(*string, (char **)NULL, 2);
printf("REP: %d\n", int_rep);
return int_rep;
}
The subsequent error I get is:
==21==ERROR: AddressSanitizer: stack-buffer-overflow on address 0x7ffda9f47a08 at pc 0x000000500cdf bp 0x7ffda9f47980 sp 0x7ffda9f47978
- READ of size 8 at 0x7ffda9f47a08 thread T0
I thought this could be due to the null-terminating character so I played around with modifying the length variable (+/- 1) in the for-loop within fromBinaryToInt but that hasn't changed anything.
I also considered the for-loop only accessing the first element and nothing more - but my understanding is I've sent through the memory address and the length of the block so the for-loop should have access to the indexes.
Any help would be greatly appreciated,
Cheers :)
In this code:
int index_of_holder = 0;
for(int i = 2; i >= 0; i--){
printf("%c", buffer[i]);
temp_holder[index_of_holder] = buffer[i];
}
index_of_holder is never changed, so all the characters are put in temp_holder[0]. The rest of temp_holder remains uninitialized.
This:
int fromBinaryToInt(char *string[], int length)
declares string to be an array of pointers to char. It is indeed passed &temp_holder, which may be considered to be a pointer to the first element of an array of one pointer to char. However, a more normal usage is to declare a simple pointer to char
int fromBinaryToInt(char *string, int length)
and pass it temp_holder, as in fromBinaryToInt(temp_holder, 3).
As it is, where it is used here:
printf("%c", *string[i]);
This takes element i of the array. When i is 0 in the loop, that is fine, it takes the first element, which exists and is a pointer to char, and then deferences it with * and prints that. However, when i is 1, it attempts to take the second element of the array. That element does not exist, and the resulting behavior is undefined.
If the parameter were merely char *string, then this printf could be:
printf("%c", string[i]);
and, in calling strtol, you would simply pass string rather than *string:
int int_rep = strtol(string, (char **)NULL, 2);
Firstly, bug in below line, index_of_holder remains same all the time, please increment it.
temp_holder[index_of_holder] = buffer[i];
Secondly, in fromBinaryToInt() string is single pointer only so you can't do *string[i]); in the next printf statement.
Here is the working code
int fromBinaryToInt(char *string, int length){
for(int i = 0; i < length; i++){
printf("%c", string[i] ); /*since string is single pointer now you can do like before you did */
}
int int_rep = strtol(string, (char **)NULL, 2);
printf("REP: %d\n", int_rep);
return int_rep;
}
int main() {
char * temp_holder = (char *)malloc(sizeof(char) * 4);
char buffer[4] ="011";
int index_of_holder = 0;
for(int i = 2; i >= 0; i--){
printf("%c", buffer[i]);
temp_holder[index_of_holder] = buffer[i];
index_of_holder++;
}
printf("\n");
int decimalValue = fromBinaryToInt(temp_holder, 3);/* no need to pass address of temp_holder */
printf("DECIMAL_VALUE: %d\n", decimalValue);
return 0;
}

Hex to ascii in c using visual studio

I'm facing some issues while I use toascii() it converts any int to ascii, but not int < 10, it returens \x1 or \x2 and so but not the ascii symbol which it should represent. so, any help please.
My code be like:
char* PostUnpack()
{
char* InStr = "04214FABF666DCE7";
int Len = strlen(InStr);
int Count, OutCount = 0;
int IntToHex;
char HexToChr[3] = "";
char TempCnv;
char RetStr[20] = "" ;
for(Count = 0; Count < Len; Count++)
{
strncpy(HexToChr,&InStr[Count],2);
IntToHex = (int) strtol(HexToChr, NULL, 16);
TempCnv = IntToHex;
toascii(TempCnv);
RetStr[OutCount] = TempCnv;
strncpy(HexToChr, "", strlen(HexToChr));
Count++;
OutCount++;
}
return RetStr;
actually in debug it be like:
\x4!O«öfÜç
while it should be :
!O«öfÜç
because I don't want to print the out put, but I use the return value to be used by some encryption method, and now when I pass this incorrect return value it make an incorrect encryption.
As already pointed out, one of the issues may be that toascii(), although working as designed, is not be producing it's converted value in the way you expect. You must use the return value of the function to get the converted value. For example, as you have called it:
toascii(TempCnv);//the converted value is returned, and you are not capturing it.
^^^^
use either a direct assignment statement to capture the value like this:
char c = toascii(0x51); //example value should produce ASCII character 3
Or you can use the string function sprintf() to place the converted value into a variable:
char c = 0;
sprintf(c, "%c", toascii(0x51));
Also, the range of printable ASCII characters is 0x20 - 0x7E. There is a paper that discusses the problems that are encountered when attempting to work with non-printable characters here
heres one that works
char * conv(char * str)
{
int l = strlen(str);
char buff[3];
buff[2] = 0;
int oidx = 0;
char *out = malloc(l/2 + 1);
int i;
for( i = 0; i < l; )
{
buff[0]= str[i++];
buff[1] = str[i++];
long x = strtol(buff, 0,16);
out[oidx++] = x;
}
out[oidx] = 0;
return strdup(out);
}
int main(void) {
char* InStr = "04214FABF666DCE7";
char* ans = conv(InStr);
free(ans);
}
does not deal with odd length input. Note the allocation of return buffer and freeing by caller. And no check of malloc
It seems the point of toascii() is to limit a value to using at most 7 bits, i.e. toascii(x) is equivalent to x &= 127. This might not be what you expect.
See the documentation for details.

Increment Char Array Pointer

Is it possible to increment/advance a char array like I can a char pointer?
For example I can do this for a char pointer:
while (*cPtr)
printf("c=%c\n", *(cPtr++));
But I am not able to do this:
// char cArray[] = "abcde";
while (*cArray)
printf("c=%c\n", *(cArray++)); // Compile error: 19 26 [Error] lvalue required as increment operand
The purpose is to be able to iterate over a char array when I dont know the length of the array. My thinking is that I just want to advance till I find a null character I guess unless theres an easier way?
char a[] = "abcde";
int index = -1;
while (a[++index])
printf("c=%c\n", a[index]);
Is it possible to increment/advance a char array like I can a char pointer?
Unlike pointers, arrays are not lvalues and you can't modify it. That's a major difference between arrays and pointers.
Do something like that:
char cArray[] = "abc def";
char *p = &cArray[0];
while (*p)
printf("c=%c\n", *(p++));
You can do:
for(int i = 0; i < 5; i++) // if you know the length
printf("c=%c\n", a[i]);
or get the size with sizeof() and replace i < 5 with i < size:
int size = (sizeof(a) / sizeof(*a))
I have used this with success under keil uVision:
char buffer[512];
uint8_t var[512]; // uint8_t = integer 8bit
for(int i = 0; i < 128; i = i + 4)
sprintf(&buffer[i],"%03d,", var[y]); //this will put 4 bytes in buffer
Better way to do this:
char buffer[128];
uint8_t int_buffer[24]; // gets updated in an interrupt - some sensors values
uint8_t i = 0;
uint8_t PrintSize = 0;
while(/*myFile is smaller than 1Mb..*/)
{
PrintSize = 0;
i = 0;
while(i < 23)
{
PrintSize += sprintf(buffer + PrintSize,"%01d,",int_buffer[i]);
i++;
}
PrintSize += sprintf(buffer + PrintSize,"%01d\n", int_buffer[23]);
//write buffer to a file in my app
}
File content is like this:
41,1,210,243,120,0,210,202,170,0,14,28,0,0,0,1,85,0,5,45,0,0,0,1
40,1,215,255,119,0,215,255,170,0,14,37,0,0,0,1,85,0,5,46,0,0,0,1

how to convert a int variable to char *array in C with malloc?

I'm doing a school project and this problem came up.
by the way, i can't use library.
How to convert a int variable to char array?
I have tried this but it didn't work, tried a lot of other things and even magic doesn't work...
char *r = malloc(sizeof(char*));
int i = 1;
r[counter++] = (char) i;
Can someone help me?
Thank you for your time.
In your code, you should allocate for char size and not char *. Please try with this code segment
char *r = malloc(sizeof(char) * N); // Modified here
int i = 1;
r[counter++] = i & 0xff; // To store only the lower 8 bits.
You could also try this:
char *r = malloc(sizeof(char));
char *s = (char*)&i;
r[counter++] = s[0];
This is an other funny way to proceed and it allows you to access the full int with:
s[0], s[1], etc...
Do you mind losing precision? A char is generally 8 bits and an int is generally more. Any int value over 255 is going to be converted to its modulo 255 - unless you want to convert the int into as many chars as is takes to hold an int.
Your title seems ot say that, but none of the answers give so far do.
If so, you need to declare an array of char which is sizeof(int) / sizeof(char) and loop that many times, moving i >> 8 into r[looop_var]. There is no need at all to malloc, unless your teacher told you to do so. In whch case, don't forget to handle malloc failing.
Let's say something like (I am coding this w/o compiling it, so beware)
int numChars = sizeof(int) / sizeof(char);
char charArry[numChard]; // or malloc() later, if you must (& check result)
int convertMe = 0x12345678;
int loopVar;
for (loopVar = 0; loopvar < numChars)
{
charArry[loopVar ] = convertMe ;
convertMe = convertMe >> 8;
}
If you can't use the library, you can't use malloc.
But this will work:
int i = 0;
char *p = (char *)&i;
p[0] = 'H';
p[1] = 'i';
p[2] = '!';
p[3] = '\0';
printf("%s\n", p);
Assuming your int is 32bit or more (and your char is 8).
It then follows that if you have:
int i[100];
You can treat that as an array of char with a size equal to sizeof (i). i.e.
int i[100];
int sz = sizeof(i); // probably 400
char *p = (char *)i; // p[0] to p[sz - 1] is valid.
You can use a union instead. Assuming that sizeof int == 4,
typedef union {
int i;
char[4] cs;
} int_char;
int_char int_char_pun;
int_char_pun.i = 4;
for (int i = 0; i < 4; i++) {
putchar(int_char_pun.cs[i]);
}
Be careful; int_char.cs usually won't be a null-terminated string, or it might be, but with length < 4.
if you don't want to include the math library:
unsigned long pow10(int n);
void main(){
char test[6] = {0};
unsigned int testint = 2410;
char conversion_started = 0;
int i=0,j=0;float k=0;
for(i=sizeof(test);i>-1;i--){
k=testint/pow10(i);
if(k<1 && conversion_started==0) continue;
if(k >= 0 && k < 10){
test[j++]=k+0x30;
testint = testint - (k * pow10(i));
conversion_started=1;
}
}
test[j]=0x00;
printf("%s",test);
}
unsigned long pow10(int n){
long r = 1;
int q = 0;
if(n==0) return 1;
if(n>0){
for(q=0;q<n;q++) r = r * 10;
return r;
}
}
NOTE: I didn't care much about the char array length, so you might better choose it wisely.
hmm... what is wrong with the code below
char *r = malloc(sizeof(char) * ARR_SIZE);
int i = 1;
sprintf(r,"%d",i);
printf("int %d converted int %s",i,r);
will it now work for you

Resources