Programmatically mock and test C function at execution - c

Yesterday I was asking myself a question.
Does it is possible to programmatically "brute force" all the calls to a specific function into a program, and test if the error cases of this call is always properly handled ?
Example:
int main(void)
{
char *mallocforfun = NULL;
char **matrix = NULL;
if ((matrix = (char **)malloc(sizeof(char*) * 42)))
{
for (int i = 0; i < 42; i++)
{
matrix[i] = (char *)malloc(sizeof(char) * 42);
bzero(matrix[i], 42);
}
matrix[i] = NULL;
}
mallocforfun = (char*)malloc(sizeof(char) * 42);
...
// do some stuff and free everything
return (0);
}
So in this example, if we would test malloc function, the tester will put three breakpoint:
int main(void)
{
char *mallocforfun = NULL;
char **matrix = NULL;
1st: if ((matrix = (char **)malloc(sizeof(char*) * 42)))
{
for (int i = 0; i < 42; i++)
{
2nd: matrix[i] = (char *)malloc(sizeof(char) * 42);
bzero(matrix[i], 42);
}
matrix[i] = NULL;
}
3rd: mallocforfun = (char*)malloc(sizeof(char) * 42);
...
// do some stuff and free everything
return (0);
}
Run the program, change malloc function return into an error value, see if it crash, delete last tested breakpoint, rerun, and so on.
I want to verify that I have handled all error returns by running the program repeatedly in an environment where malloc fails once at each call site in turn on subsequent runs of the program. (Thank's to #Mic for the explicit formulation)
I think it's possible to do something like this with non-stripped binary with gdb script. I searched by myself but can't find anything looking like that.
So I feel like I have a "keyword" missing. Do you know if this kind of test have a specific name, or a tool doing something like that ?

Related

How to return a char** as a function argument

I have a function that returns a pointer to pointers of chars (char**). The function takes 2 arguments
int* num_paths: a pointer to an integer to indicate the number of strings to be returned.
int* errno: a pointer to an integer to indicate an error code. This can contain different values, so I cannot simply check if NULL is returned in case of error.
Some example code is written below (with the majority of error checks omitted for simplicity):
char** get_paths(int* num_paths, int* errno) {
char* path1 = NULL;
char* path2 = NULL;
char** paths = NULL;
if(errno == NULL) {
printf("Set errno in case of error, but cannot dereference NULL pointer\n");
goto exit;
}
path1 = calloc(1, strlen("foo") + 1);
path2 = calloc(1, strlen("bar") + 1);
strcpy(path1, "foo");
strcpy(path2, "bar");
*num_paths = 2;
paths = calloc(1, *num_paths*sizeof(char *));
paths[0] = path1;
paths[1] = path2;
*errno = 0;
exit:
return paths;
}
int main(void) {
char** paths = NULL;
int num_paths = 0;
int errno = 0;
paths = get_paths(&num_paths, &errno);
if(errno != 0) {
return -1;
}
for(int i = 0; i < num_paths; i++) {
printf("%s\n", paths[i]);
free(paths[i]);
}
free(paths);
}
The problem I have with this is that I can't set the error code in case a NULL pointer is passed as argument for errno. You could argue that this is a user error, but I would still like to avoid this situation in the first place.
So my question is: can I rewrite my get_paths function such that it returns an integer as error code, but also returns a char** through the function arguments without resorting to char*** like in the following example:
int get_paths_3(char*** paths, int* num_paths) {
char* path1 = NULL;
char* path2 = NULL;
path1 = calloc(1, strlen("foo") + 1);
path2 = calloc(1, strlen("bar") + 1);
strcpy(path1, "foo");
strcpy(path2, "bar");
*num_paths = 2;
*paths = calloc(1, *num_paths*sizeof(char *));
(*paths)[0] = path1;
(*paths)[1] = path2;
return 0;
}
This is pretty much the only case where "three star" pointers are fine to use. It's fairly common practice in API design to reserve the return value for error codes, so this situation isn't uncommon.
There are alternatives, but they are arguably not much better. You could abuse the fact that void* can be converted to/from char** but it isn't much prettier and less type safe:
// not recommended
int get_paths_4 (void** paths, size_t* num_paths)
{
char* path1 = calloc(1, strlen("foo") + 1);
char* path2 = calloc(1, strlen("bar") + 1);
strcpy(path1, "foo");
strcpy(path2, "bar");
*num_paths = 2;
char** path_array;
path_array= calloc(1, *num_paths*sizeof(char *));
path_array[0] = path1;
path_array[1] = path2;
*paths = path_array;
return 0;
}
...
void* vptr;
size_t n;
get_paths_4 (&vptr, &n);
char** paths = vptr;
for(size_t i=0; i<n; i++)
{
puts(paths[i]);
}
A more sound alternative might be wrap all your parameters into a single struct type and pass that one as a pointer.
Unfortunately you cannot mixing return types in C is a terrible mistake and should not be done, you can either:
return the pointer you need and add a error code to a variable
return the error code and add the pointer to a variable
Both are valid strategies and I'd pick the one that matches the rest of your code to have consistency.

Realloc arguments vector and string manipulation

I am asked to implement a reduced system shell that needs to be coded in C, and I have to achieve some of the features of an UNIX shell.
One of them is the replacement of ~[USER] to USER home dir, if USER appears, or the default environment variable "HOME" if it doesn't. I could write the code that iterates all over the commands (i.e. "ls ~hxshfx | sort | echo $var" -> argvv = {ls ~hxshfx, sort, echo $var}, but I can't figure out what to code if I want to change the own argvv value (i.e, ls /home/hxshfx | sort | echo a). I know I should use realloc but I don't understand how to use it when no malloc has been called. I do have another if statement for variables like $VAR but the problem is the same, the reallocation of information at argvv[i][j] position.
This is my code snippet:
void metacharacters (char *** argvv) {
int i, j;
char user, var, * aux, * toSubstitute, * name;
user = '~';
var = '$';
for (i = 0; argvv[i] != NULL; i++) {
for (j = 0; (aux = argvv[i][j]) != NULL; j++) {
if (aux[0] == user) {
struct passwd * pswd;
if (strlen(aux) > 1) {
name = (char *) struct passwd * pswd;malloc(sizeof(char) * (strlen(aux)-1));
strncpy(name, aux + 1, strlen(aux)-1);
pswd = getpwnam(name);
toSubstitute = pswd -> pw_dir;
free(name);
} else {
toSubstitute = getenv("HOME");
}
// TODO changes to argvv[i][j]
} else if (aux[0] == var) {
name = (char *) malloc(sizeof(char) * (strlen(aux)-1));
strncpy(name, aux + 1, strlen(aux)-1);
toSubstitute = getenv(name);
// TODO changes to argvv[i][j]
free(name);
}
}
}
}
The other thing I don't know how to solve is the shell function "set". When the shell recieves, i.e., "set myvar 1" it should use putenv to set the environment variable "myvar". I do think my function used to set the variable works okay:
void setVariable (char * arg1, char * arg2) {
int ret;
char * command = strdup(arg1);
strcat(command, "=");
strcat(command, arg2);
// i.e., at this point, command = "myvar=1", since arg1 = myvar; arg2 = 1
ret = putenv(command);
if (ret < 0) {
perror("putenv");
exit(1);
}
printf("%s=%s\n", arg1, getenv(arg1));
// I do think it works because getenv(arg1) works fine
free(command);
}
But, in the next iteration (or just outside the function setVariable), if I check what is the value of the environment variable "myvar", I always got null, no matter what. Also, if I print all the environment variables, there is no entry with "myvar" name, which is strange since, in the setVariable function, I had getenv(name) and that goes OK.
Thank you.

Proper resource handling in Elixir NIF

I am trying to implent a NIF for simple linear algebra. Here is my internal structure for matrix:
typedef struct la_matrix {
uint rows, columns;
double **data;
} la_matrix;
And here is a "constructor" for it:
la_result
la_matrix_constructor(la_matrix **res,
const uint rows,
const uint columns)
{
if (rows == 0 || columns == 0)
return dimensional_problems;
// allocate memory for meta-structure
*res = malloc(sizeof(la_matrix));
if (*res == NULL)
return null_ptr;
// allocater memory for array of pointers to rows
(*res)->data = malloc(rows * sizeof(double*));
if ((*res)->data == NULL) {
free(*res);
return null_ptr;
}
//allocate memory for each row
uint i = 0;
bool failed = false;
for (; i < rows; i++) {
(*res)->data[i] = malloc(columns * sizeof(double));
if ((*res)->data[i] == NULL) {
failed = true;
break;
}
}
if (failed) {
// one step back, since i-th row wasn't allocated
i -= 1;
for(; i < ~((uint) 0); i--)
free((*res)->data[i]);
free((*res)->data);
free(*res);
return null_ptr;
}
(*res)->rows = rows;
(*res)->columns = columns;
return ok;
}
Then I have two wrappers for NIF -- one for constructor:
static ERL_NIF_TERM
nif_matrix_constructor(ErlNifEnv *env,
int argc,
const ERL_NIF_TERM *argv)
{
uint rows, columns;
enif_get_uint(env, argv[0], &rows);
enif_get_uint(env, argv[1], &columns);
la_matrix **mat_res = enif_alloc_resource(LA_MATRIX_TYPE, sizeof(la_matrix *));
la_matrix *mat_ptr;
la_result result = la_matrix_constructor(&mat_ptr, rows, columns);
if (result != ok)
return enif_make_atom(env, "err");
memcpy((void *) mat_res, (void *) &mat_ptr, sizeof(la_matrix *));
ERL_NIF_TERM term = enif_make_resource(env, mat_res);
enif_release_resource(mat_res);
return term;
}
And one to test if the constructor works correctly:
static ERL_NIF_TERM
nif_matrix_rows(ErlNifEnv *env,
int argc,
const ERL_NIF_TERM *argv)
{
la_matrix *mat_ptr;
if(!enif_get_resource(env, argv[0], LA_MATRIX_TYPE, (void **) &mat_ptr))
return enif_make_atom(env, "err");
return enif_make_uint(env, mat_ptr->rows);
}
It seems that the constructor wrapper works perfectly fine (I've tested it with using printf), but nif_matrix_rows returns strange results, e.g.
iex(1)> mat = LinearAlgebra.matrix(2,3)
""
iex(2)> LinearAlgebra.rows(mat)
1677732752
And directly passing LinearAlgebra.matrix(2,3) to LinearAlgebra.rows twice results in segfault:
iex(3)> LinearAlgebra.rows(LinearAlgebra.matrix(2,3))
1543520864
iex(4)> LinearAlgebra.rows(LinearAlgebra.matrix(2,3))
zsh: (core dumped) iex -S mix
(Note different results for the "same" matrices).
I was following Andrea Leopardi's tutorial with minor (I don't really sure if they are so) changes to fight gcc warnings. Most important, IMHO, was this part
la_matrix *mat_ptr;
if(!enif_get_resource(env, argv[0], LA_MATRIX_TYPE, (void **) &mat_ptr))
return enif_make_atom(env, "err");
while Andrea Leopardi uses
db_conn_t **conn_res;
enif_get_resource(env, argv[0], DB_RES_TYPE, (void *) conn_res);
db_conn_t *conn = *conn_res;
But it looks invalid for me since, AFAIR, (void *) conn_res assumes that conn_res was initalized.
Here is an error which occurs when I use Andrea's way:
src/nif.c: In function ‘nif_matrix_rows’:
src/nif.c:72:3: warning: ‘mat_res’ is used uninitialized in this function [-Wuninitialized]
enif_get_resource(env, argv[0], LA_MATRIX_TYPE, (void *) mat_res);
And calling LinearAlgebra.rows from iex causes segfault.
Could one tell me a proper way for handling structures in NIFs?
P.S. Sorry for C code, I've never wrote something more than bunch of helloworlds.
The problem was indeed in nif_matrix_rows: with my code Elixir passes a pointer to a pointer to a structure (la_matrix **) and I assumed that it would be a proper pointer.
So, quick fix is
static ERL_NIF_TERM
nif_matrix_rows(ErlNifEnv *env,
int argc,
const ERL_NIF_TERM *argv)
{
la_matrix const **mat_res;
if(!enif_get_resource(env, argv[0], LA_MATRIX_TYPE,(void **) &mat_res))
return enif_make_atom(env, "err");
la_matrix const *mat_ptr = *mat_res;
return enif_make_uint(env, mat_ptr->rows);
}
However, I'll wait some time for more elegant solution and won't accept this answer so far.

Assigning values to members of structures

I am currently working on a project for a course in C programming and have run into a problem. I am still quite new to the language C but have experience programming Java.
My program runs into a problem when I try to assign a value to a char * variable member of a struct. The code in question follows below:
void ReadFile(ComponentType * Data, int * numEl, int * numNodes)
{
size_t index;
FILE * dataFile;
char * data;
float * value;
numEl = malloc(sizeof(int *));
numNodes = malloc(sizeof(int*));
Data = malloc(6 * sizeof(ComponentType));
* numEl = 0;
* numNodes = 0;
index = 0;
if((dataFile = fopen("mydata.dat", "r")) == NULL)
puts("Error - file \"mydata.dat\" could not be opened!");
else
{
while(!feof(dataFile))
{
fscanf(dataFile, "%s", data);
Data[index].name = (char *)malloc(strlen(data)+1);
strcpy(Data[index].name, data);
fscanf(dataFile, "%s", data);
Data[index].node1 = (char *)malloc(strlen(data)+1);
strcpy(Data[index].node1, data);
fscanf(dataFile, "%s", data);
Data[index].node2 = (char *)malloc(strlen(data)+1);
strcpy(Data[index].node2, data);
fscanf(dataFile, "%f", value);
Data[index].value = * value;
int i = char2int(CircuitData[index].node1);
if(i > * numNodes)
* numNodes = i;
i = char2int(CircuitData[index].node2);
if(i > * numNodes)
* numNodes = i;
(* numEl)++;
(* numNodes)++;
index++;
}
fclose(dataFile);
}
free(Data);
free(numEl);
free(numNodes);
}
The structure is defined as follows:
typedef struct
{
char * name;
char * node1;
char * node2;
float value;
} ComponentType;
I have run a debug on the program and what basically happens is that the file is read correctly and the value stored in data is correct however printing out Data[index].name either causes a segmentation fault when formatted as a char * or, in the debug program, prints out 0x0. In short, the values read from the file are not being copied into the structure variable I want them in.
Any suggestions/help would be appreciated.
Thank you.
EDIT: I am using Linux 64-bit to code
EDIT 2: I added the entire function in which the error occurs with the changes suggested below
First: when you debug your program, check what sizeof(data) is.
You will be surprised to find it is 8 (the size of a pointer), and NOT 6 (the size you allocated)
This is because sizeof measures the size of the type, and data is a char*, (aka. a pointer).Pointers are 8-bytes. (on a 64-bit system. Other systems are different)
This causes you to allocate 8 bytes for Data[index].name.
Next: You cannot copy data from one array to another using the = operator, as you tried to do with:
Data[index].name = data;
To do it properly:
fscanf(dataFile, "%s", data);
// Measure the length of data, and allocate enough space (including the null-termiantor)
Data[index].name = malloc(strlen(data) + 1);
// Copy from data into Data[index].name. For greater safety, look into strcpy_s
strcpy(Data[index].name, data);

Another malloc/free dilemma

I haven't used C or C++ in over 6 years and am a bit rusty. I am writing some quick test code for a graph-traversal algorithms. The code accepts an adjacency-list style input. However I'm running into some issues with free/malloc.
There are two issues with my code:
When I run the code without free and without the getchar the code hangs when I use VC++ cntrl-f5. This is remedied when I use getchar(). Does anyone know why?
When I run the code with free the code hangs. I've tried to debug the code and it hangs exactly at the free statement. Any suggestions as to how I can fix this?
Also please let me know if I'm doing anything dangerous with this code. Header file is omitted.
void * s_malloc(size_t size){
void * ret_pntr = malloc(sizeof(size));
if (ret_pntr == NULL){
printf ("error");
exit(1);
}
return (void *)malloc(sizeof(size));
}
void initialize_graph(graph * G1, int num_vertices){
int i = 0 ;
G1->num_vertices = num_vertices;
G1->node_list = (node**)s_malloc(sizeof(node*)*num_vertices);
for (i = 0; i < num_vertices; i ++){
G1->node_list[i] = (node *)s_malloc(sizeof(node));
}
}
void free_everything(graph * G1){
int i = 0;
node * ref = NULL;
for (i = 0; i < G1->num_vertices; i++){
ref = G1->node_list[i];
recursive_remove(ref);
}
free(G1->node_list);
}
void recursive_remove(node * ref){
if (ref == NULL){
return;
}
else{
recursive_remove(ref->next);
}
free(ref);
}
int main(){
int i = 0;
graph * G1 = (graph*)s_malloc(sizeof(graph));
G1->init = &initialize_graph;
G1->init(G1, 10);
G1->remove = &free_everything;
G1->node_list[0]->value = 1;
G1->node_list[0]->next = (node*)s_malloc(sizeof(node));
G1->node_list[0]->next->value = 2;
G1->node_list[0]->next->next = NULL;
G1->node_list[1]->value = 10;
printf("%d\n", G1->node_list[0]->next->value);
printf("%d\n", G1->node_list[1]->value);
G1->remove(G1);
free(G1);
getchar();
}
One thing that jumps out immediately is that in
void * s_malloc(size_t size){
void * ret_pntr = malloc(sizeof(size));
if (ret_pntr == NULL){
printf ("error");
exit(1);
}
return (void *)malloc(sizeof(size));
}
you are allocating twice, leaking the first allocation, and are not checking result of the second allocation. Another is that your malloc call should be
malloc(size)
not
malloc(sizeof(size))
Because in your current code you underallocate all your memory (each allocation will only give you 4 bytes at a time), your accesses stomp all over... I'm surprised execution actually makes it to the getchar() or free().
What's not clear is why you are trying to emulate OOP in C while using VC++. If you rewrite this in C++ using STL containers to hold your nodes and with indices instead of pointers, I think a lot of your problems will disappear. But right now debugging this mess for you is not going to be fun for any one.
An even better solution is to use an existing graph library like Boost Graph

Resources