Calling function from library in any other project than library crash - c

I have made a library that handle strings in c.
I've added it in another project CMakeLists. Issue is that, whenever i want to call a function from that library, it crash.
However, if i call the same function from the library itself, no crash, the function call is handled properly.
I kept thinking that i did something wrong with my CMakeLists but as far as i'm aware and the different methods i used to arrive to the same conclusion, it doesn't look like it anymore.
I tried running the test in question in gdb and this is what it returned
Starting program: C:\Users\s\Documents\Repo\C\Projet\lib\rule\build\test-create-destroy.exe
gdb: unknown target exception 0xc0000135 at 0x7ffdfa70cf40
gdb: unknown target exception 0xc0000135 at 0x7ffdfa70cf40
Program received signal ?, Unknown signal.
0x00007ffdfa70cf40 in ntdll!RtlRaiseStatus () from C:\Windows\SYSTEM32\ntdll.dll
I've read that it could be an issue related to memory allocation errors, but if this was the case, why would i be able to call the function without any error directly from my library?
replit of fairly simple example: https://replit.com/#Mrcubix-Mrcubix/EmbellishedOldfashionedBaitware#lib/rule/src/test-create-destroy.c
Here is the function called in the library in question, to keep it simple:
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
typedef struct _String
{
unsigned int size;
char *string;
} String;
String *create_string(char *chr)
{
String *str = malloc(sizeof(String));
str->size = strlen(chr);
str->string = malloc(str->size + 1);
memcpy(str->string, chr, str->size);
str->string[str->size] = '\0';
return str;
}
void destroy_string(String *str)
{
free(str);
}
Here the second library i'm calling a function from which work as it's part of the same project:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <string-struct.h>
typedef struct _rule
{
String *premise;
String *conclusion;
} rule;
rule *create_rule(String *premise, String *conclusion)
{
rule *r = calloc(1, 16);
r->premise = premise;
r->conclusion = conclusion;
return r;
}
void destroy_rule(rule *r)
{
free(r);
}
here is the CMakeLists used by Rulestruct:
cmake_minimum_required(VERSION 3.0)
project("Rulestruct")
find_package(Stringstruct)
include_directories(${STRINGSTRUCT_INCLUDE_DIRS})
link_directories(${STRINGSTRUCT_LIB_DIRS})
add_library(rulestruct SHARED "${CMAKE_CURRENT_SOURCE_DIR}/src/rule-struct.c" "${CMAKE_CURRENT_SOURCE_DIR}/src/rule-struct.h")
target_link_libraries(rulestruct ${STRINGSTRUCT_LIBRARIES})
add_executable(test-create-destroy "${CMAKE_CURRENT_SOURCE_DIR}/src/test-create-destroy.c" "${CMAKE_CURRENT_SOURCE_DIR}/src/rule-struct.h")
add_dependencies(test-create-destroy rulestruct)
target_link_libraries(test-create-destroy rulestruct)
and finally, here is where i call the function from (test-create-destroy.c)
#include <assert.h>
#include <string-struct.h>
#include "rule-struct.h"
#include "rules-struct.inc"
int main(void)
{
String *premise = create_string("1 2"); // location of crash
String *conclusion = create_string("3"); // location of crash
/*rule *rule_A = create_rule(premise, conclusion);
assert(string_char_equal(rule_A->premise, "1 2"));
assert(!string_char_equal(rule_A->premise, "3"));
assert(string_char_equal(rule_A->conclusion, "3"));
assert(!string_char_equal(rule_A->conclusion, "1 2"));
destroy_rule(rule_A);*/
destroy_string(premise);
destroy_string(conclusion);
}
Here are screenshots of bin, lib and cmake-gui: https://imgur.com/a/3OdrC2D
I could probably fix it on every project provided i know what i did wrong and why,
So if anyone could provide further explanation then i'll glad to read it.
I will also take tips about issues or potential issues related to my CMakeLists as i have a hard time understanding any of it, needing to mix multiple examples and the documentation to have a very small bit of understanding of why something is done this or that way.
TLDR: Function called elsewhere than inside the library = crash, accept tips about other parts of the presented data (CMakeLists).
Gladly accept further explanation of the core of the issue.

Related

How can I cause a "initscr" break with ncurses?

I know this is a weird question, but I want to get the "initscr" function error mentioned by the doc (getting invalid pointer and an error message on stderr) to test if a wrapper works properly.
But I don't find any information about that. I'm currently working with ncurses 6.2.
After few research, I have found that the invalid pointer is really a NULL, not just an empty one pointing on anywhere.
But I'm not able to break the function...
If someone know how to help me to break down this, feel free to leave a comment.
The following program:
#include <curses.h>
#include <malloc.h>
#include <stdlib.h>
bool my_malloc_disabled;
void *malloc(size_t size) {
if (my_malloc_disabled) {
return NULL;
}
void *__libc_malloc(size_t);
return __libc_malloc(size);
}
int main() {
my_malloc_disabled = 1;
initscr();
}
does:
$ gcc file.c -lcurses
$ ./a.out
Error opening allocating $TERM.

How to color output in C for cross-platform app

I am new and I know how to color output only in Unix/Linux systems:
#include <stdio.h>
int main(void) {
printf("\033[1;31mRed Message\033[0m.");
}
But this is not works in Windows cmd.exe, only in Unix terminal.
I am writing cross-platform app and want to know how can I do this in Windows cmd.exe too.
This also does not works:
1.
#include <stdio.h>
int main(void) {
printf("%c[1;31mRed Message%c[0m", 27, 27);
}
2.
#include <stdio.h>
int main(void) {
printf("[1;31m Red Message [0m");
}
This works, but I think this is just a bug:
If I type system(""); before printf then it works.
#include <stdio.h>
int main(void) {
system("");
printf("\033[1;31m Red Message \033[0m");
}
Thanks
If you want to make your library crossplatform, I would use the following approach:
Have a library, with the same functions, let's say:
void printInRed(const char* string). (In a headerfile)
After that you write two or more implementations.
One for windows:
//TODO: Errorchecking
void printInRed(const char* string){
HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE);
//TODO: Extract magic number
//See https://stackoverflow.com/a/4053879/13912132
SetConsoleTextAttribute(hConsole, 12);
puts(string);
}
And another one for unix-like OS:
//TODO: Errorchecking
void printInRed(const char* string){
printf("\033[1;31m%s\033[0m.", string);
}
Then you can check at compile time, which version to compile.
The first approach is to use #ifdefs, but this will make the code a bit messy.
Another approach would be to use a build-system like CMake to select at build time, which one to build. A buildsystem requires a bit of learning, but will help you to make maintaining a crossplatform library simpler.

Segmentation fault on trying to execute value at environment variable

Hey so I was trying to solve a problem for beginners ctf event.
And this is the code that I am trying to run.
#include <stdio.h>
#include <stdlib.h>
int main(){
int (*func)();
func = getenv("MYENV");
func();
return 0;
}
I created a MYENV environment like this :
export MYENV=ls
but on running the code, it throws a segmentation fault (core dumped). I don't understand why.
The func function is basically calling the environment variable whose value is a simple command that I set. Why is it throwing an error.
I'm very new at linux and shell, so I'm sorry if this is too naive.
In C, if you want to run a system command, you have to use the system function (or one of the exec functions but that's more complicated):
#include <stdio.h>
#include <stdlib.h>
int main() {
char* cmd = getenv("MYENV");
system(cmd);
return 0;
}
If you're looking to run arbitrary code, you can inject shell code into it:
export MYENV=$'\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\x89\xe1\xb0\x0b\xcd\x80'
You can learn more here.

Using dlsym() to stub malloc/free leads to segmentation fault

I started to dabble in unit testing C code (using check) and stubbing functions. I am trying to unit
test a small library of data structures that I wrote and wanted to test how it would react to OOM. So I
wrote a simple stubs.c file containing:
#include <stdlib.h>
#include <errno.h>
#include <dlfcn.h>
static int malloc_fail_code = 0;
static int calloc_fail_code = 0;
void set_malloc_fail_code(int no) { malloc_fail_code = no; }
void set_calloc_fail_code(int no) { calloc_fail_code = no; }
void *malloc(size_t size)
{
static void *(*real_malloc)(size_t) = NULL;
if (!real_malloc)
real_malloc = (void *(*)(size_t)) dlsym(RTLD_NEXT, "malloc");
if (malloc_fail_code != 0) {
errno = malloc_fail_code;
malloc_fail_code = 0;
return NULL;
}
return real_malloc(size);
}
void *calloc(size_t nmemb, size_t size)
{
static void *(*real_calloc)(size_t, size_t) = NULL;
if (!real_calloc)
real_calloc = (void *(*)(size_t, size_t)) dlsym(RTLD_NEXT, "calloc");
if (calloc_fail_code != 0) {
errno = calloc_fail_code;
calloc_fail_code = 0;
return NULL;
}
return real_calloc(nmemb, size);
}
with its relative stubs.h containing the definitions for the two setters. I then compiled stubs.c as
a shared object called libstubs.so. I also compiled my library as a shared object called
libmy_lib.so.
My test code is in test.c is something like this:
#include <stdlib.h>
#include <errno.h>
#include <check.h>
#include "my_lib.h"
#include "stubs.h"
START_TEST(my_test)
{
... // using the two setters I force malloc and calloc to return null and set errno to ENOMEM
}
END_TEST
... // check boilerplate to create suite and add tests
I then linked the test executable against libmy_lib.so and libstubs.so. Running said executable greets me with a segfault. Inspecting the crash with gdb makes me believe that I encountered a stack overflow due to infinte recursion (gdb backtrace):
#0 0x00007ffff7fc143c in calloc (
nmemb=<error reading variable: Cannot access memory at address 0x7fffff7feff8>,
size=<error reading variable: Cannot access memory at address 0x7fffff7feff0>)
at stubs.c
#1 0x00007ffff7db9c88 in _dlerror_run (operate=operate#entry=0x7ffff7db94f0 <dlsym_doit>,
args=args#entry=0x7fffff7ff030) at dlerror.c:148
#2 0x00007ffff7db9570 in __dlsym (handle=<optimized out>, name=<optimized out>) at dlsym.c:70
#3 0x00007ffff7fc1487 in calloc (nmemb=1, size=32) at stubs.c
...
I tried including directly stubs.c into test.c but no luck. I also tried writing a small unit testing framework of my own that extends stubs.c and it worked. However I don't want to waste time reinventing the wheel and I am sure there is something I am doing wrong in linking since I don't know much in compilation/linking.
For compilation I am using the meson build system so I don't know how to get the exact command line arguments but I can write a MWE of my build targets:
lib = library(
'my_lib',
sources,
include_directories: includes,
install: true
)
stubs = shared_library(
'stubs',
'stubs.c',
c_args: ['-g'],
include_directories: test_includes,
link_args: ['-ldl']
)
test_exe = executable(
'test_exe',
c_args: ['-g'],
sources: 'test.c',
dependencies: check,
link_with: [stubs, lib],
include_directories: includes + test_includes
)
test('test', test_exe, suite: 'suite')
Try using LD_PRELOAD trick. The meson-ish way to accomplish it would be:
test_env = environment()
test_env.prepend('LD_PRELOAD', stubs.full_path())
test('test', test_exe, suite: 'suite', env: test_env)
note: do not link executable with stubs.

How can I make atoi work in my ADS project?

I want to use atoi function in my program, but I found it not working.
#include <ctype.h>
int value;
value=atoi(buf);
char buf points to "1000" or something like, terminated by \0. I have checked it.
But the value evaluates always to zero. I have tried strtol(), but I get the same error.
My ADS (ARM Developer Suit) is v1.2 (s3c2440). I can find the libs in armlib path (c_t_xx.l).
I use axd debug mode, so I can trace my code. I found "bl
__rt_ctype_table", so I think asm code linked right.
Please give any advice to fix this issue.
ARM might have a problem with string functions, you haven't mentioned whether it returns a value and it's incorrect (i heard it's a bug and it's better you should write the function on your own) or there is no value at all.
anyway look at the arm article about it i think it's the solution - ARM article about string functions
The following code should work,
#include <stdio.h>
#include <stdlib.h>
int main()
{
int i;
char buff[5] = "1000\0";
i=atoi(buff);
printf("i=%d\n", i);
return 0;
}
#./a.out
#i=1000

Resources