Pointer initializiation? for a specific function - c

Alright, this one's been puzzling me for a bit.
the following function encodes a string into base 64
void Base64Enc(const unsigned char *src, int srclen, unsigned char *dest)
{
static const unsigned char enc[] =
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
unsigned char *cp;
int i;
cp = dest;
for(i = 0; i < srclen; i += 3)
{
*(cp++) = enc[((src[i + 0] >> 2))];
*(cp++) = enc[((src[i + 0] << 4) & 0x30)
| ((src[i + 1] >> 4) & 0x0f)];
*(cp++) = enc[((src[i + 1] << 2) & 0x3c)
| ((src[i + 2] >> 6) & 0x03)];
*(cp++) = enc[((src[i + 2] ) & 0x3f)];
}
*cp = '\0';
while (i-- > srclen)
*(--cp) = '=';
return;
}
Now, on the function calling Base64Enc() I have:
unsigned char *B64Encoded;
Which is the argument I pass onto unsigned char *dest in the base 64 encoding function.
I've tried different initializations from mallocs to NULL to other initialization. No matter what I do I alway get an exception and if I don't initialize it then the compiler (VS2005 C compiler) throws a warning telling me that it hasn't been initialized.
If I run this code with the un-initialized variable sometimes it works and some other it doesn't.
How do I initialized that pointer and pass it to the function?

you need to allocate buffer big enough to contain the encoded result. Either allocate it on the stack, like this:
unsigned char B64Encoded[256]; // the number here needs to be big enough to hold all possible variations of the argument
But it is easy to cause stack buffer overflow by allocating too little space using this approach. It would be much better if you allocate it in dynamic memory:
int cbEncodedSize = srclen * 4 / 3 + 1; // cbEncodedSize is calculated from the length of the source string
unsigned char *B64Encoded = (unsigned char*)malloc(cbEncodedSize);
Don't forget to free() the allocated buffer after you're done.

It looks like you would want to use something like this:
// allocate 4/3 bytes per source character, plus one for the null terminator
unsigned char *B64Encoded = malloc(srclen*4/3+1);
Base64Enc(src, srclen, B64Encoded);

It would help if you provided the error.
I can, with your function above, to this successfully:
int main() {
unsigned char *B64Encoded;
B64Encoded = (unsigned char *) malloc (1000);
unsigned char *src = "ABC";
Base64Enc(src, 3, B64Encoded);
}
You definitely need to malloc space for the data. You also need to malloc more space than src (1/4 more I believe).

A base64 encoded string has four bytes per three bytes in-data string, so if srclen is 300 bytes (or characters), the length for the base64 encoded string is 400.
Wikipedia has a brief but quite good article about it.
So, rounding up srclen to the nearest tuple of three, divided by three, times four should be exactly enough memory.

I see a problem in your code in the fact that it may access the byte after the trailing null char, for instance if the string length is one char. The behavior is then undefined and may result in a thrown exception if buffer boundary checking is activated.
This may explain the message related to accessing uninitialized memory.
You should then change your code so that you handle the trailing chars separately.
int len = (scrlen/3)*3;
for( int i = 0; i < len; i += 3 )
{
// your current code here, it is ok with this loop condition.
}
// Handle 0 bits padding if required
if( len != srclen )
{
// add new code here
}
...
PS: Here is a wikipedia page describing Base64 encoding.

Related

Why can glibc strcspn() safely access memory apparently past the end of a string?

GNU libc has this implementation of strcspn(), which, quote,
Returns the length of the maximum initial segment of S
which contains no characters from REJECT.
It's clever in its implementation in that it creates a 256-entry lookup table to make the operation of finding whether a character is in the reject set a simple O(1) array lookup, as opposed to e.g. the OpenBSD implementation which uses nested loops.
However, I'm curious how the c0/c1/c2/c3 loop below can access memory past the apparent end of str without a page fault or similar.
Does the C standard, for instance, guarantee that all strings, whether on the stack or heap or statically allocated, have their allocations aligned up to 4 bytes, so it's safe to access up to 3 past the last NUL?
I've added some comments in the code below; the original (as linked above) has none whatsoever.
/* Align a pointer by rounding down to closest size. */
#define PTR_ALIGN_DOWN(base, size) ...
size_t strcspn (const char *str, const char *reject)
{
if ((reject[0] == '\0') || (reject[1] == '\0'))
return __strchrnul (str, reject [0]) - str;
// Build a lookup table containing all characters from `reject`;
// due to the way the `do/while` loop below is constructed, `table`
// will end up having `table[0] = 1` always, which works as an
// exit condition.
unsigned char p[256] = {0};
unsigned char *s = (unsigned char*) reject;
unsigned char tmp;
do
p[tmp = *s++] = 1;
while (tmp);
// Check the first 4 bytes "by hand".
s = (unsigned char*) str;
if (p[s[0]]) return 0;
if (p[s[1]]) return 1;
if (p[s[2]]) return 2;
if (p[s[3]]) return 3;
// Align the pointer (for whichever reason?)
s = (unsigned char *) PTR_ALIGN_DOWN (s, 4);
unsigned int c0, c1, c2, c3;
do
{
s += 4; // Loop over 4 characters at a time (the first 4 bytes were checked before)
c0 = p[s[0]];
c1 = p[s[1]];
c2 = p[s[2]];
c3 = p[s[3]];
}
// break if any of c0, c1, c2, or c3 is nonzero,
// i.e. if we've either found one of the characters in `reject`, or a zero
while ((c0 | c1 | c2 | c3) == 0);
size_t count = s - (unsigned char *) str;
// figure out the actual offset based on which of c0..3 is set
return (c0 | c1) != 0 ? count - c0 + 1 : count - c2 + 3;
}
That loop is preceded by the line:
s = (unsigned char *) PTR_ALIGN_DOWN (s, 4);
Which ensures that s is aligned to 4 bytes. The loop then reads 4 bytes at a time. This guarantees that even if it reads past the end of the string, the extra bytes read will still be within the same 4-byte word.
If you go strictly by the C standard, this results in undefined behavior. But glibc assumes that on the platforms it runs on, the page size is a multiple of 4 bytes, and that reading past the end of a buffer will not cause any issues as long as it's within the same page.

Char array to unsigned short conversion issue

I am trying to convert char array to unsigned short but its not working as it should.
char szASCbuf[64] = "123456789123456789123456789";
int StoreToFlash(char szASCbuf[], int StartAddress)
{
int iCtr;
int ErrorCode = 0;
int address = StartAddress;
unsigned short *us_Buf = (unsigned short*)szASCbuf;
// Write to flash
for(iCtr=0;iCtr<28;iCtr++)
{
ErrorCode = Flash_Write(address++, us_Buf[iCtr]);
if((ErrorCode &0x45)!= 0)
{
Flash_ClearError();
}
}
return ErrorCode;
}
When I see the Conversion, on us_Buf[0] I have value 12594, us_Buf[1]= 13108 like that and I have values only uptous_Buf[5]` after that it is "0" all remaining address.
I have tried to declare char array like this also
char szASCbuf[64] = {'1','2','3','4','5','6','7','8','9','1',.....'\0'};
I am passing the parameters to function like this
StoreToFlash(szASCbuf, FlashPointer); //Flashpointe=0
I am using IAR embedded workbench for ARM. Big enedian 32.
Any suggestions where i am doing wrong?
Thanks in advance.
Reinterpreting the char array szASCbuf as an array of short is not safe because of alignment issues. The char type has the least strict alignment requirements and short is usually stricter. This means that szAscBuf might start at address 13, whereas a short should start at either 12 or 14.
This also violates the strict aliasing rule, since szAscBuf and us_Buf are pointing at the same location while having different pointer types. The compiler might perform optimisations which don't take this into account and this could manifest in some very nasty bugs.
The correct way to write this code is to iterate over the original szASCBuf with a step of 2 and then do some bit-twiddling to produce a 2-byte value out of it:
for (size_t i = 0; i < sizeof(szAscbuf); i += 2) {
uint16_t value = (szAscbuf[i] << 8) | szAscbuf[i + 1];
ErrorCode = Flash_Write(address++, value);
if (ErrorCode & 0x45) {
Flash_ClearError();
}
}
If you really intended to treat the digit characters with their numeric value, this will do it:
uint16_t value = (szAscbuf[i] - '0') + (szAscbuf[i + 1] - '0');
In case you just want the numeric value of each character in a 2-byte value (1, 2, 3, 4, ...), iterate over the array with a step of 1 and fetch it this way:
uint16_t value = szAscbuf[i] - '0';
That's normal !
Your char array is "123456789123456789123456789" or {'1','2','3','4','5','6','7','8','9','1',.....'\0'}
But in ASCII '1' is 0x31, so when you read the array as a short * on a big endian architecture, it gives :
{ 0x3132, 0x3334, ... }
say differently in decimal :
{ 12594, 13108, ... }

Char string overwriteing other string

I´m making a program that builds a binary message. I´m using char strings to hold the binary value. So I´ve initialized a bunch of char strings that has the default values. Then I combine them by running a for loop and read them into a large string (aismsg/ais_packet). And everything worked fine untill I added msg14Text[], then the string I´m building (aismsg/ais_packet) gets shortened as shown below (even though I´m not using the variable). Seems like when I add msg14Text[], it changes the value of one of the other strings. Is this maybe a memory allocation problem?
Part of the code:
char ais_packet[257]; //Allokerer array for ais data pakke.
char aismsg[175]; //Allokerer array for meldingen.
int burst_nr = 1; //Indicates with burst it is transmittin (1-7).
char ramp_up[] = "00000000"; //Ramp up buffer.
char train_seq[] = "010101010101010101010101"; //Training sequence 24 bits of alternating 0-1.s
char hdlc_flag[] = "01111110"; //HDLC Start and END flag.
char buffer[] = "000000000000000000000000"; //Data packet buffer.
char msgID1[] = "000001"; //msg. 1.
char msgID14[] ="010100"; //msg. 14.
char repeat[] = "00"; //repetert 0 ganger.
char mmsi[] = "000111010110111100110100010101"; //Gir 123456789 som MMSI.
char nav_stat[] = "1111"; //Gir 15= AIS-SART test, endres til 14 (1110) for aktiv AIS-SART.x'
char rot[] = "10000000"; //Rate of Turn -128 betyr ikkje tilgjengelig.
char sogBin[] = "1111111111"; //Tilsvarer 1023 = not available = default.
char pos_acc[] = "0"; //Posisjonsnøyaktighet over 10m. 1 = under 10m.
char lonBin[] = "0110011110010001101011000000"; // Tilsvarer 181 grader som er default verdi for Longitude.
char latBin[] = "011010000010010000101000000"; // Tilsvarer 91 grader som er default verdi for Latitude.
char cogBin[] = "111000010000"; //Tilsvarer 3600 = not available = default.
char headingBin[] = "111111111"; //511 = not available = default
char timestamp[] = "111100"; //Tid siden melding er generert, 60 = default = ts not available.
char spec_man[] = "01"; //Special manouver 0 = default, 1 = not engaged in special manouver
char spare[] = "000";
char spareMSG14[] = "00"; //Reserved.
char raim[] = "0"; //RAIM 0 = not in use.
char comm_state[] = "00011100000000000000"; // First 2bit: Sync state: 3 = no UTC sync = default, 0 = UTC sync. 0011100000000000000
char msg14Text[] = "100100101101111011111100"; //CAUSING TROUBLE!!!! for AIS melding 14 står "Test" med 6-bit ASCII koding.
The enitre code for the function can be found at pastebin.com/wj0RxyLX
Output of ais packet with msg14Text[]:
00000000
Output of ais packet without msg14Text[]:
0000000001010101010101010101010101111110000001000001110101101111001101000101011111100000000011010000000000000110100011000101111000000101100100000100001100101110000100000000110011111000100000011100000000000000001000100110100101111110000000000000000000000000
aispacket should consist of the following variables:
ramp_up[] + train_seq[] + hdlc_flag[] + Datapacket(168bit) + crc(16bit) + hdlc_flag[] + buffer[] + '\0'
"Is this maybe a memory allocation problem?"
You don't explicitly allocate any memory in your code. Note that char repeat[] = "00"; is statically allocated array whose size is equal to size of 3 chars and whose content is being initialized by string literal "00".
Problem is most likely in copying of these strings into ais_packet since you do that in nonstandard way (character by character) which causes your code to be hard to read and it's quite easy to make a mistake there:
for(int k=0; k<256; k++)
{
...
if(k==256) // are you sure that value of k will reach 256 ?
I recommend you to use C-style functions that have been created for this purpose: Craete ais_packet by copying first string into it by using strcpy and keep extending content of this ais_packet by appending other strings by using strcat.
This question will also help you: Using strcat in C
At the end of the ugly for (k=0; k < 168; k++) { if ... else if ...} loop
else if(k==168)
{
aismsg[k] = '\0';
k=0;
}
This will make either (k <=168) the loop run forever, or (k <168) never be executed. (there are more instances of this pattern)
BTW another way to do the same (also faster) would be
....
unsigned dst=0;
memcpy (array+dst, src1, 123);
dst += 123;
memcpy(array+dst, src2, 234);
dst += 234;
...
array[dst] = 0;
Just a thought, but if you are building binary messages, why not use actual binary instead of char arrays? Here's a way to use structs inside a union to bit pack binary data.
// declaration
typedef union
{
uint32_t packed;
struct {
uint16_t sample1: 12; // 12 bits long
uint16_t sample2: 14;
uint16_t 6; // unused bits
} data;
} u1;
// instantiation
u1 pack1;
// setting
pack1.data.sample1 = 1234;
//getting
uint16_t newval = pack1.data.sample2;
// setting bit 6 in sample 1
pack1.data.sample1 |= (1 << 6);
// setting lo nibble in sample1 to 0101
pack1.data.sample1 &= 0b11110101;
// getting the whole packed value
uint32_t binmsg = pack1.packed;

How to XOR scramble a string in C and back again with the same function?

I am trying to obfuscate a string in a program. Currently, I only have a simple string reversal working. I would like to be able to perform XOR scrambling on the data to make it much more secure, however the method I have tried is not working.
The same function and input type is used to decode the string. This is no problem with string reversal, as it just reverses back, but can this be done easily with XORing without getting too complex? I would prefer if the process kept just the one string, like the reversal does. Here is my reversal function.
void reverse_string(unsigned char *buf, int length)
{
int i;
unsigned char temp;
for (i = 0; i < length / 2; i++)
{
temp = buf[i];
buf[i] = buf[length - i - 1];
buf[length - i - 1] = temp;
}
}
And here is the attempt at a XOR function
void charxor(char * text, int len) {
const unsigned char enc[8]={173,135,131,121,110,119,187,143};
char ch;
int i;
int ind=0;
for (i=0;i<len;i++) {
ch=*text++;
if (ch)
*text = ch ^ enc[ind++];
ind %=8;
}
}
Can anyone help? Would be much appreciated!
You seem to be overcomplicating things a bit. Try this instead:
void charxor (unsigned char *text, int len) {
const unsigned char enc[8] = {173,135,131,121,110,119,187,143};
int i;
for (i = 0; i < len; i++) {
text[i] ^= enc[i % 8];
}
}
Note that the XOR operation can introduce null chars into the string, so you really do need to keep track of its length instead of just relying on the presence of a trailing null char.
Also keep in mind that, while this may indeed be relatively speaking "much more secure" than just reversing the string, any reasonably clever person with access to enough samples of the output can probably figure out how to decode it in around fifteen minutes or so.
this is a pbox, it would require you to make a non repeating integer key - random - same size as said block. the last block would start with the offset which could be just random data. Doesn't cover null terminators so decide where the data is going / what your doing with it. you could realloc(buff, "A") to use memmove. make 3 64 bit boxes, and a subset of 16 4 bit boxes from the output of the 64 and it starts to look like a poor implementation of des, which openssl has build into it. The fundamental advantage is being able to encrypt/decrypt with the same function / address space. This could also allow you to encrypt in place without a extra buffer. KSZ is the length of your block(s)/key
char
*zecr
(bff, zbf, ky, ze)
char *bff;
char *zbf;
unsigned int ky[];
short ze;
{
/* main encrypt decrypt function */
int i=0;
while( i < KSZ ) {
int dx = ky[i];
if( ze == 1 ) { // encrypt
char c = bff[dx];
sprintf(zbf + i, "%c", c);
} else { // decrypt
char c = bff[i];
char tk[1] = "";
sprintf(tk, "%c", c);
memmove(zbf +dx, tk, 1);
}
i++;
}
return zbf;
}
xoring is a binary operation, which will yield vastly different results depending on how you cast it. You got the right idea using ocdec but if the idea is to keep it simple im going to assume you don't actually know assembly despite the requested reference, stick with c calls its simpler for how you are most likely going to be using the data.
-the female orgasm, that's the myth. -SUN TZU

Memory loss in following code when the CPU is 32 bit processor

I have a function to convert integer to string .The function is
char * Int_String(int Number)
{
char* result;
NAT size = 1;
if (Number > 9) {
size = (NAT)log10((double) Number) + 1;
} else if (Number < 0) {
size = (NAT)log10((double) abs(Number)) + 2; /* including '-' */
}
size++; /* for '\0' */
result = (char *) memory_Malloc(sizeof(char) * size);
sprintf(result, "%d", Number);
return result;
}
NAT is typedef unsigned int
Number is int
I am using this function in the following manner
char *s2;
char **Connections;
Connections = memory_Malloc(nc*sizeof(char*));
char con[]="c_";
k1=1;
for (i=0; i<nc ; i++){
s2 = Int_ToString(k1);
Connections[i]= string_Conc(con,s2);
string_StringFree(s2);
k1= k1+1;
}
And the functionschar* string_Conc(const char *s1, const char *S2) is
{
char* dst;
dst = memory_Malloc(strlen(s1) + strlen(s2) + 1);
strcpy(dst, s1);
return strcat(dst,s2);
}
I am using following methods to free its memory:
for(i=0; i<nc; i++){
memory_Free(Connections[i],sizeof(char));
}
memory_Free(Connections,nc*sizeof(char*));
The problem that i am getting is: i can free all the allocated memory when nc<=9.But when it is >=10 leakes memory in the multiple of 4 bytes with each increase in number. How can I remove the problem.Any help will be appreciated.
EDIT
void memory_Free(POINTER Freepointer, unsigned int Size)
Thanks,
thetna
You don't show the implementation of memory_Free (neither memory_Malloc), so we don't know why you need to pass the supposed size of the memory block to be freed as a 2nd parameter (the standard free() doesn't need this). However, here
memory_Free(Connections[i],sizeof(char));
it is certainly wrong: sizeof(char) is 1 on most platforms, but the size of the allocated block is at least 4 bytes for each string in the array (as the strings contain "c_" plus at least one digit plus the terminating '\0').
Update
Looking through the source code you linked, this indeed seems to be the cause of your problem! The code inside memory_Free seems to align memory block sizes - I can assume that to 4-byte boundaries, which is very common. In this case, if the passed Size is 1, it happens to be corrected to 4 - exactly the right value in case of single digit numbers as shown above! However, numbers greater than 9 are converted to (at least) two digits, thus the size of the converted string is already 5. A block of 5 bytes is most probably allocated as an aligned block of 8 bytes under the hood - but since memory_Free is always called with a Size of 1, it always frees only 4 bytes. This leaves 4 bytes leaking per each number above 9, precisely as you described in your comment above!
To fix this, you need to modify the line above to
memory_Free(Connections[i], strlen(Connections[i]) + 1);

Resources