Unexpected behavior of C function parameters - c

I have a function:
void sbox(uint8_t* sb1, uint8_t* sb2, uint8_t* sb3, uint8_t* sb4, uint8_t* primitive, size_t size) {
if(!sb1 || !sb2 || !sb3 || !sb4 || !primitive) {
printf("*** error: Polynomials cannot be null in sbox()\n");
return;
}
uint8_t timeSb1, timeSb2, timeSb3, timeSb4;
timeSb1 = 62;
timeSb2 = 5;
timeSb3 = 17;
timeSb4 = 62;
sb1 = sb(sb1, sb1, sb1, size, primitive, timeSb1);
sb2 = sb(sb2, sb2, sb2, size, primitive, timeSb2);
sb3 = sb(sb3, sb3, sb3, size, primitive, timeSb3);
sb4 = sbr4(sb4, sb4, sb4, size, primitive, timeSb4);
}
where the third parameter of functions sb() and sbr4() is the result of an operation applied on the first two parameters, within those functions. The remaining functions are:
uint8_t* sb(uint8_t* a, uint8_t* b, uint8_t* c, size_t size, uint8_t* primitive, size_t times) {
return mul2polyTimes(a, b, c, size, primitive, times);
}
uint8_t* mul2polyTimes(uint8_t* a, uint8_t* b, uint8_t* c, size_t size, uint8_t* primitive, size_t times) {
if(!a || !b || !primitive) {
printf("*** error: Polynomials cannot be null in mul2poly()\n");
return NULL;
}
for(int i = 0; i < times; i++) {
c = mul2poly(a, b, c, size, primitive);
}
return c;
}
uint8_t* mul2poly(uint8_t* a, uint8_t* b, uint8_t* c, size_t size, uint8_t* primitive)
{
if(!a || !b || !primitive) {
printf("*** error: Polynomials cannot be null in mul2poly()\n");
return NULL;
}
uint8_t carry, prodSize;
uint8_t *temp;
carry = 0;
temp = NULL;
prodSize = 2*size;
c = (uint8_t*)allocate1DArray((void*)c, prodSize);
temp = (uint8_t*)allocate1DArray((void*)temp, prodSize);
for(int i = size - 1; i >= 0; i--)
temp[i + size] = a[i];
if(b[size-1]) {
for(int i = size - 1; i >= 0; i--)
c[i + size] = a[i];
}
for(int i = size - 2; i >= 0; i--) {
lShiftPoly(temp, prodSize);
if(b[i]) {
for(int ii = prodSize - 1; ii >= 0; ii--) {
if(carry) {
if(c[ii] && temp[ii]) {
c[ii] = 1;
carry = 1;
} else if(c[ii] || temp[ii]) {
c[ii] = 0;
carry = 1;
} else {
c[ii] = 1;
carry = 0;
}
} else {
if(c[ii] && temp[ii]) {
c[ii] = 0;
carry = 1;
} else if(c[ii] || temp[ii]) {
c[ii] = 1;
carry = 0;
} else {
c[ii] = 0;
carry = 0;
}
}
}
}
}
uint8_t reduce;
reduce = 0;
for(int i = 0; i < size; i++) {
if(c[i]) {
reduce = 1;
break;
}
}
if(reduce) {
for(int i = 0; i < prodSize; i++)
c[i] ^= primitive[i];
}
uint8_t* d;
d = NULL;
d = (uint8_t*)allocate1DArray((void*)d, size);
for(int i = size; i < prodSize; i++) {
d[i-size] = c[i];
}
free(c);
c = d;
return c;
}
I've noticed that, after calling sbox(), the values of the referenced values remain unaltered, but when inspected within the function they are being set accordingly. What am I missing here?
Note: the reasons that these functions take such a large number of parameters are not programming related.

This line in mul2poly():
c = (uint8_t*)allocate1DArray((void*)c, prodSize);
doesn't propagate the new allocation outside the particular invocation of mul2poly(). You'll need to pass the third argument as a uint8_t** and dereference it appropriately to do what you want in C.

Related

pass by value not supported XDP

I am creating a function to loop through some loops and try to match a set. It is supposed to work fine, but unfortunately, it is not. I get a "pass by value not supported" error. How can I fix this?
int matchSet(Program p, int match[], int action)
{
int matchState = 0;
int match[4] = {3,4,5,6}; //set as example
int p.set[10] = {2,1,3,4,5,6,9,10,11,12}; //set as example (normal p.set)
for (int i = 0; i < 10; i++)
{
if (matchState != 2)
{
if (p.set[i] == match[0] && p.set[i + 1] == match[1])
{
matchState = 0;
for (int j = 0; j <= 4; j++)
{
bpf_printk("test");
if (matchState == 0)
{
bpf_printk("test3");
if (p.set[i] != match[j])
{
bpf_printk("test4");
matchState = 1;
break;
}
}
}
if (matchState == 0)
{
bpf_printk("test6");
matchState = 2;
}
}
}
}
if(matchState == 2) {
return action;
}
}
I call the function by:
Program p;
.....
int set[10] = {2,1,3,4,5,6,9,10,11,12};
p.set = set;
int match[4] = {3,4,5,6};
matchSet(p, match, 1);
Error:
error: pass by value not supported 0x1aca7c8: i64 = GlobalAddress<i32 (%struct.Program*, i8*, i32)* #matchSet> 0
You need to change your function to take a pointer to a Program like so:
int matchSet(Program *p, int match[], int action){
...
And then also change your callsite:
Program p;
matchSet(&p, match, 1);

C program takes an absurdly long amount of time (or enters infinite loop)

The function is given a string (for example "communism") and checks whether or not its suffix is a part of a wordbank - the program takes an absurdly long time (or is infinite-looped, I don't know but I suspect the first). here's an example of the suffix wordbank (reversed)
char* noun_suffixes[] = { "msi", "re", "sci", "ssen", "tnem", "tsi" };
Here's the function: (n is the number of words in the bank, *str is the word).
bool is_suffix_in_dict(char* str, char* dict[], int n)
{
printf("first checkpoint reached");
char strRev[MAX_LEN + 1] = { 0 }, strToCheck[MAX_LEN + 1] = { 0 };
unsigned int len = strlen(str);
for (unsigned int i = 0; i < len; i++)
{
strRev[len - i] = *(str + i);
}
for (unsigned int i = 0, j = 0; i < len; i++)
{
while (strRev[i] < 'a' || strRev[i] > 'z')
{
i++;
}
if (i < len)
{
strToCheck[j] = strRev[i];
if (binarySearch(dict, n, strToCheck))
{
printf("second check reached - positive");
return TRUE;
}
j++;
}
}
printf("second check reached - neg");
return FALSE;
}
the function calls upon this one-
bool binarySearch(char* dict[], int n, char s[MAX_LEN + 1])
{
int last = n, first = 0, mid = n / 2;
while (first < n)
{
int cmpVal = strcmp(dict[mid], s);
if (cmpVal < 0)
{
printf("cmpVal<0");
first = mid + 1;
mid = (first + last) / 2;
}
else if (cmpVal > 0)
{
printf("cmpVal>0");
last = mid;
mid = (first + last) / 2;
}
else
{
return TRUE;
}
}
return FALSE;
}

Adding two really large numbers in C

I am trying to add two really large numbers (say 30 digit long) in C. Here is my code:
#include <stdio.h>
#include <string.h>
int main()
{
char a[30] =
{
'1','1','1','1','1','1','1','1','1','1','1','1','1','1','1',
'1','1','1','1','1','1','1','1','1','1','1','1','1','1','1'
. };
b[30] =
{
'8','8','8','8','8','8','8','8','8','8','8','8','8','8','8',
'8','8','8','8','8','8','8','8','8','8','8','8','8','8','8'
};
int i, j, k, carry = 0, sum[1001];
if(strlen(a) >= strlen(b))
{
k = strlen(a);
}
else
{
k = strlen(b);
}
for(i = strlen(a); i > 0; i--)
{
for(j = strlen(b); j > 0; j--)
{
sum[k] = (a[i]-'0') + (b[j]-'0') + carry;
carry = sum[k]/10;
k--;
}
}
for(i = 0; i < k; i++)
{
printf("%d", sum[i]);
}
printf("\n");
return 0;
}
but it gives me no answer at all. What is wrong with it?
Small change to the code above to take care of the last trailing carry value if it > 0:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(){
int temp = 0;
char *fp ;
char *sp ;
char bigger = '\n';
char a[10] =
{
'1','2','3','4','5','6','7','8','9','1'
};
char b[10] =
{
'9','8','9','8','9','8','9','8','9','8'
};
int i, c, j, k, carry = 0, sum[1001] = {0};
if(sizeof(a) > sizeof(b))
{
k = sizeof(a);
j = sizeof(b);
bigger = 'a';
}
else
{
k = sizeof(b);
j = sizeof(a);
bigger = 'b';
}
c = k;
fp = malloc(k);
sp = malloc(j);
if (bigger == 'a')
{
strncpy(fp, a, k);
strncpy(sp, b, j);
}
else
{
strncpy(fp, b, k);
strncpy(sp, a, j);
}
for(i = strlen(fp); i > 0; i--,j--)
{
if(j>0 )
{
temp = *(fp+i-1)-'0' + *(sp+j-1)-'0' + carry;
if(temp < 10)
{
sum[k] += temp;
carry = 0;
}
else
{
sum[k] += temp%10;
carry = temp/10;
}
}
else
{
temp = *(fp+i-1)-'0' + carry;
if(temp < 10)
{
sum[k] += temp;
carry = 0;
}
else
{
sum[k] += temp%10;
carry = temp/10;
}
}
k--;
}
if(carry > 0)
printf("%d", carry);
for(i = 1; i <= c; i++)
{
printf("%d", sum[i]);
}
printf("\n");
return 0;
}
This should work. I changed the way your loops should work and also added some checks to ensure alignment and consistency in case the length of the large numbers change.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main()
{
int temp = 0;
char *fp ;
char *sp ;
char bigger = '\n';
char a[30] =
{'1','1','1','1','1','1',
'1','1','1','1','1','1',
'1','1','1','1','1','1','1','1','1','1','1','1','1',
'1','1','1','1','1'
};
char b[30] =
{
'8','8','8','8','8','8','8','8','8','8','8','8','8','8',
'8','8','8','8','8','8','8','8','8','8','8','8','8','8',
'8','8'
};
int i, c, j, k, carry = 0, sum[1001] = {0};
if(sizeof(a) > sizeof(b))
{
k = sizeof(a);
j = sizeof(b);
bigger = 'a';
}
else
{
k = sizeof(b);
j = sizeof(a);
bigger = 'b';
}
c = k;
fp = malloc(k);
sp = malloc(j);
if (bigger == 'a')
{
strncpy(fp, a, k);
strncpy(sp, b, j);
}
else
{
strncpy(fp, b, k);
strncpy(sp, a, j);
}
for(i = strlen(fp); i > 0; i--,j--)
{
if(j>0 )
{
temp = *(fp+i-1)-'0' + *(sp+j-1)-'0' + carry;
if(temp < 10)
{
sum[k] += temp;
carry = 0;
}
else
{
sum[k] += temp%10;
carry = temp/10;
}
}
else
{
temp = *(fp+i-1)-'0' + carry;
if(temp < 10)
{
sum[k] += temp;
carry = 0;
}
else
{
sum[k] += temp%10;
carry = temp/10;
}
}
k--;
}
if(carry > 0)
printf("%d", carry);
for(i = 1; i <= c; i++)
{
printf("%d", sum[i]);
}
printf("\n");
return 0;
}

Segfault in Merge - Sort in C

I am trying to sort an array of structures of size 5500 using merge sort.
However, I am getting a segmentation fault pretty quickly because I am not allowed to use VLA. so I have to create 2 extra arrays of size 5500 each time I call merge-sort recursively.
I would appreciate a fix for my problem. I will provide my code here:
void merge(Student rightArr[], Student leftArr[], Student mergedArr[], int sizeOfRight, int sizeOfLeft) {
int rightArrIndex = 0;
int leftArrIndex = 0;
int mergedArrIndex = 0;
while (leftArrIndex < sizeOfLeft && rightArrIndex < sizeOfRight) {
char *ptrLeft, *ptrRight;
long gradeLeft = strtol(leftArr[leftArrIndex].grade, &ptrLeft, BASE_COUNT);
long gradeRight = strtol(rightArr[rightArrIndex].grade, &ptrRight, BASE_COUNT);
if (gradeLeft > gradeRight) {
mergedArr[mergedArrIndex] = rightArr[rightArrIndex];
rightArrIndex++;
} else {
mergedArr[mergedArrIndex] = leftArr[leftArrIndex];
leftArrIndex++;
}
mergedArrIndex++;
}
if (leftArrIndex == sizeOfLeft) {
for (int i = mergedArrIndex; i < (sizeOfLeft + sizeOfRight); i++) {
mergedArr[i] = rightArr[rightArrIndex];
rightArr++;
}
} else {
for (int i = mergedArrIndex; i < (sizeOfLeft + sizeOfRight); i++) {
mergedArr[i] = leftArr[leftArrIndex];
leftArr++;
}
}
}
void mergeSort(Student studentsArray[], int amountOfStudents) {
if (amountOfStudents <= 1) {
return;
}
int leftSize = (amountOfStudents / 2);
int rightSize = (amountOfStudents - leftSize);
Student leftArr[5500], rightArr[5500];
for (int i = 0; i < leftSize; i++) {
leftArr[i] = studentsArray[i];
}
for (int i = 0; i < rightSize; i++) {
rightArr[i] = studentsArray[i + leftSize];
}
mergeSort(leftArr, leftSize);
mergeSort(rightArr, rightSize);
merge(rightArr, leftArr, studentsArray, rightSize, leftSize);
}
Ok, I think this should do what you want. It assumes that Student and BASE_COUNT have been defined:
#include <stdlib.h>
#include <stdio.h>
void merge(Student studentsArr[],
int leftSize, int rightSize,
Student scratchArr[])
{
Student *leftArr = studentsArr;
Student *rightArr = studentsArr + leftSize;
int leftIx = 0, rightIx = 0, mergeIx = 0, ix;
while (leftIx < leftSize && rightIx < rightSize) {
long gradeLeft = strtol(leftArr[leftIx].grade, NULL, BASE_COUNT);
long gradeRight = strtol(rightArr[rightIx].grade, NULL, BASE_COUNT);
if (gradeLeft <= gradeRight) {
scratchArr[mergeIx++] = leftArr[leftIx++];
}
else {
scratchArr[mergeIx++] = rightArr[rightIx++];
}
}
while (leftIx < leftSize) {
scratchArr[mergeIx++] = leftArr[leftIx++];
}
// Copy the merged values from scratchArr back to studentsArr.
// The remaining values from rightArr (if any) are already in
// their proper place at the end of studentsArr, so we stop
// copying when we reach that point.
for (ix = 0; ix < mergeIx; ix++) {
studentsArr[ix] = scratchArr[ix];
}
}
void mergeSortInternal(Student studentsArray[],
int amountOfStudents,
Student scratchArr[])
{
if (amountOfStudents <= 1) {
return;
}
int leftSize = amountOfStudents / 2;
int rightSize = amountOfStudents - leftSize;
mergeSortInternal(studentsArray, leftSize, scratchArr);
mergeSortInternal(studentsArray + leftSize, rightSize, scratchArr);
merge(studentsArray, leftSize, rightSize, scratchArr);
}
#define MAX_ARR_SIZE 5500
void mergeSort(Student studentsArray[], int amountOfStudents)
{
if (amountOfStudents <= 1) {
return;
}
if (amountOfStudents > MAX_ARR_SIZE) {
fprintf(stderr, "Array too large to sort.\n");
return;
}
Student scratchArr[MAX_ARR_SIZE];
mergeSortInternal(studentsArray, amountOfStudents, scratchArr);
}
The top-level sort function is mergeSort, defined as in the original post. It declares a single scratch array of size MAX_ARR_SIZE, defined as 5500. The top-level function is not itself recursive, so this scratch array is only allocated once.

Can someone explain what is wrong in my memory pool?

I compiled in C with -O3 and as share library on Linux Fedora x64. I used some mallocs after one. It seems when I work with wmemcpy and other functions in this family the change in one memory makes change in other...
I may violate size of memory? Or the problem is in my implementation?
Thanks in advance!
char* ur_free_available(struct memory_pool* pool, uint64_t sz)
{
uint64_t size = sz + sizeof(struct _MyPage);
if(pool->free_pos > 0)
{
if(pool->free_blocks[pool->free_pos - 1].pNext - pool->free_blocks[0].pNext > size)
{
uint64_t i, j;
char *addr;
struct _MyPage mpg;
for(i = 1; i < pool->free_pos; ++i)
{
if(pool->free_blocks[i].pNext - pool->free_blocks[0].pNext > size)
{
mpg.pPrev = NULL;
mpg.pNext = pool->free_blocks[i-1].pNext;
break;
}
}
pool->free_blocks[0].pPrev = NULL;
for(j = i; j < pool->free_pos; ++j)
{
if(j > 0)
pool->free_blocks[j-i].pPrev = pool->free_blocks[j-1].pPrev;
pool->free_blocks[j-i].pNext = pool->free_blocks[j].pNext;
}
pool->free_pos -= i;
pool->free_pos++;
memcpy(addr,(char*)&mpg, sizeof(mpg));
return &addr[0] + sizeof(struct _MyPage);
}
}
return NULL;
}
char* ur_mem_alloc(struct memory_pool* pool, uint64_t sz)
{
char *addr;
struct _MyPage mpg;
uint64_t size = sz + sizeof(mpg);
uint64_t j = 0, c, op;
if(pool->init_pos_is != 7)
{
//bzero(pool, sizeof(pool));
pool->init_pos_is = 7;
pool->free_pos = 0;
pool->hp_position = 0;
pool->st_position = 0;
mpg.pPrev = NULL;
for(c = 0; c < HP_CNT; c++)
pool->_extramem[c] = NULL;
pool->free_blocks[0].pNext = NULL;
//pool->_bytes = malloc(ST_MYPAGE_NO*ST_MYPAGE_SIZE);
//pthread_mutex_lock(&llk1);
_mpool = pool;
//pthread_mutex_unlock(&llk1);
atexit(equit);
}
if((addr = ur_free_available(pool, size)) != NULL)
{
return &addr[0];
}
op = pool->hp_position;
if(size + (ST_MYPAGE_SIZE * pool->st_position) > ST_MYPAGE_NO * ST_MYPAGE_SIZE)
{
uint64_t i;
for(i = 0; i < HP_CNT; ++i)
{
if(size < (pow(8, i)-pool->hp_position)*HP_MYPAGE_SIZE)
{
j = i;
if(pool->_extramem[i] == NULL)
{
pool->hp_position = 0;
pthread_mutex_lock(&llk2);
pool->_extramem[i] = (char*)malloc((uint64_t)pow(8, i) * HP_MYPAGE_SIZE);
pthread_mutex_unlock(&llk2);
}
break;
}
}
addr = &pool->_extramem[j][pool->hp_position*HP_MYPAGE_SIZE];
mpg.pPrev = (struct _MyPage*)&pool->_extramem[j][op*HP_MYPAGE_SIZE];
//printf("j %u %u %u\n", j, (uint64_t)size, (uint64_t)(pow(8, i-1))*HP_MYPAGE_SIZE);
pool->hp_position += floor(size/HP_MYPAGE_SIZE) + 1;
mpg.pNext = (struct _MyPage*)&pool->_extramem[j][pool->hp_position*HP_MYPAGE_SIZE];
memcpy(addr,(char*)&mpg, sizeof(mpg));
return &addr[0] + sizeof(struct _MyPage);
//
}
else
{
if(pool->st_position != 0)
{
mpg.pPrev = (struct _MyPage*)&pool->_extramem[j][(pool->hp_position)];
}
mpg.pNext = NULL;
pool->st_position += floor(size/ST_MYPAGE_SIZE);
addr = &pool->_bytes[(uint64_t)(pool->st_position-floor(size/ST_MYPAGE_SIZE)) * ST_MYPAGE_SIZE];
memcpy(addr,(char*)&mpg, sizeof(mpg));
return &addr[0] + sizeof(struct _MyPage);
}
}
void ur_mem_free(struct memory_pool* pool, char *addr)
{
if(addr == NULL) return;
pool->free_blocks[pool->free_pos].pPrev = pool->free_blocks[pool->free_pos].pNext;
pool->free_blocks[pool->free_pos].pNext = (struct _MyPage*)(addr - sizeof(struct _MyPage));
pool->free_pos++;
}
Breafly looking into function ur_free_available, the variable addr is not initialized, but you memcpy to it corrupting a random memory region. Then you try to return something using the same non-initialized pointer.

Resources