Shared library function does working correctly after first dlopen - c

I am creating a websocket server in C. Since taking a server down, recompiling it, and running it again is counterproductive to what a server app should do, I am looking for ways to dynamically load in my functions so that I can keep the main server app running while being able to alter / create new functions that will be used in it. I created a function that allows me to call a function by name with correct arguments like you would a normal function call, but when I go to call it the second time it does not do the same thing the second time I call it dynamically. To lay out my problem by steps, consider the following situations:
Situation 1
Start server application without calling sendMessage dynamically.
Connect to the websocket server via browser.
After successful connection send a message to the server (I use Hello World)
Server will echo the message the client sent.
Send the same message to the server again.
Server will echo message again. (this is when the server sendMessage function is not loaded dynamically
Repeating steps 5 and 6 will not cause the client to disconnect.
Now for the situation using a dynamic version of the servers sendMessage function to echo the client message.
Situation 2
Start server application while allowing sendMessage to be called using loadFunction.
Connect to the websocket server via browser.
After successful connection send a message to the server (again I use Hello World)
Server will echo the message the client sent like it should.
Send the same message to the server again.
This time the server does not echo the message the client sent.
Sending more messages after the first will eventually cause the connection to end (This is where I am having a problem
Situation 1 is when my function sendMessage is called normally (not through loadFunction) while situation 2 is where I replace sendMessage with my loadFunction call that loads the library holding sendMessage, assigns it to a location function variable (see code) and call the function like it would normally.
I am thinking that the problem lies with the write function in sendMessage when I dynamically load it. But the function works perfectly when I don't load it dynamically which is odd to me.
My question is why is why would my sendMessage function operate differently from when I call it normally and when I call it dynamically? Below is some code and output from both situations
sendMessage.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <unistd.h>
#include "include/structs.h"
//#include "include/functions.h"
/*
* sendMessage: this function is used then we want to send message (s)
* of length (len) from the server to a client (sock)
*
* ARGUMENTS
* sock: the socket where we want the message to go
* s: A string containing the message we want to send
* len: the length of the string s
*/
void *sendMessage(int sock, char *s, int len) {
int frameCount;
uint16_t len16;
char frame[10];
char *reply = malloc(sizeof(char) * (len + 8));
frame[0] = '\x81';
if (len <= 125) {
frame[1] = len;
frameCount = 2;
} else if (len >= 126 && len <= 65535) {
frame[1] = 126;
len16 = htons(len);
memcpy(frame + 2, &len16, 2);
frameCount = 4;
} else {
frame[1] = 127;
//NOTE: HAVE NOT FULLY CONFIGURED A MESSAGE OF THIS LENGTH (TODO)
//frame[2] = (char)( ((char)len >> 56) & (char)255 );
//frame[3] = (char)( ((char)len >> 48) & (char)255 );
//frame[4] = (char)( ((char)len >> 40) & (char)255 );
//frame[5] = (char)( ((char)len >> 32) & (char)255 );
//frame[6] = (char)( ((char)len >> 24) & (char)255 );
frame[7] = (char)( ((char)len >> 16) & (char)255 );
frame[8] = (char)( ((char)len >> 8) & (char)255 );
frame[9] = (char)( ((char)len) & (char)255 );
frameCount = 10;
}//END IF
memcpy(reply, frame, frameCount);
memcpy(reply + frameCount, s, len);
//printf("sock: %d\ts: %s\tlen: %d\n", sock, s, len);
if (write(sock, reply, strlen(reply)) <= 0) {
printf("\n\nWE ARE NOT WRITING!!\n\n");
} else {
//printf("we did write\n");
}//END IF
free(reply);
reply = NULL;
return NULL;
}//END FUNCTION
loadFunction.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <dlfcn.h>
#include "include/functions.h"
int checkForError(char *error) {
if (error != NULL) {
printf("ERROR: %s\n", error);
exit(EXIT_FAILURE);
}//END IF
return 0;
}//END IF
void * loadFunction(char *func, void ** args) {
void *handle;
//void * (*alterStruct)(int sock, char *action);
int filenameLength;
char * filename;
//void *(*funcPtr);
filenameLength = strlen("lib/lib") + strlen(func) + strlen(".dll");
filename = malloc(sizeof(char) * (filenameLength + 1));
strcpy(filename, "lib/lib");
strcat(filename, func);
strcat(filename, ".dll");
handle = dlopen(filename, RTLD_LAZY);
free(filename);
if (!handle) {
checkForError(dlerror());
}//END IF
dlerror();
if (strncmp(func, "sendMessage", strlen(func)) == 0) {
void * (*funcPtr)(int, char *, int);
//*(void **) (&funcPtr) = dlsym(handle, func);
funcPtr = (void *)dlsym(handle, func);
checkForError(dlerror());
(*funcPtr)((int)args[0], (char *)args[1], (int)args[2]);
//free(*(void **)(&funcPtr));
//*(void **) (&funcPtr) = NULL;
}// else if (strncmp(func, "alterStruct", strlen(func)) == 0) {
//void * (*funcPtr)(int sock, char *action);
//} else if (strncmp(func, "execute", strlen(func)) == 0) {
//void * (*funcPtr)(const char *command, clientStruct s, FILE **in, FILE **out, FILE **err);
//} else {
//void * (*funcPtr)(int sock, char *s, int len);
//}//END IF
dlclose(handle);
handle = NULL;
return NULL;
return NULL;
}//END loadFunction
If you need more code to solve this problem I have it accessable on GitHub here (the dynamic branch is where the problem can be found)
Also, I am using Cygwins' GNU gcc compiler (which I have never have a problem compiling on) to compile my application and libraries so I may not have access to certain Linux commands (for example dlmopen). That said, please do not say use a different compiler because I've had no other problems thus far and I do not intend on changing how I compile my code.
I did not document the command I use to compile just the libsendMessage.dll used in loadFunction. you can obtain it using the following
gcc -c -fPIC sendMessage.c
mv sendMessage.o objects/sendMessage.o
gcc -shared -o lib/libsendMessage.dll objects/sendMessage.o libfunctions.c
Thank you in advance.

I have figured out my problem and it is quite an odd one.
When i was testing the sendMessage function using my dynamic method i printf exactly what was being sent through the socket and apparently it was sending the correct message. However, it was also sending the characters from my filename variable in the loadFunction function which to me is strange that the memory address was accessable to sendMessage when it was malloced, freed and set to NULL way before the function call to the dynamic sendMessage was called.
Solution
After I opened my library with dlopen(filename, RTLD_LAZY) I used memset(filename, '\0', filenameLength) to write null characters to the memory address of filename making the string contain all null characters which when accessed as a character counts as a end of string.
I'm not sure why I am having to use memset so much in this application but i know that it has fixed string bugs for me multiple times.

Related

Compiling an already written C script. Visual Studios 2017

I have an already written script for C that I want to use to go along with Texmod. There was post about it a long time ago but I can't access it. Basically it lets you use TexMod with arguments for the .exe like -log. I have downloaded Visual Studios 2017 and have tried compiling it using the developers console by cd to the folder than cl 'script.c' to compile it. It makes an .exe and .obj but does nothing past that, even when I double click the .exe The problem is I know java and have never done anything in the C language. Here is the code:
#include <stdio.h>
#include <windows.h>
#include <tlhelp32.h>
UINT WINAPI EzGetPid(LPCSTR procName, UINT *pid, UINT size);
int main(int argc, char *argv[])
{
if (argc < 1) {
puts("You must specifie the arguments");
return 1;
}
UINT pid = 0;
if (!EzGetPid("Texmod.exe", &pid, 1)) {
puts("You must open Texmod first.");
return 1;
}
BYTE shellcode_tramp[] = "\x58\x6A\x00\x6A\x00\x68\x00\x00\x00\x00\xFF\xE0";
UINT size_tramp = 12;
char arguments[0x500] = {0};
strcpy(arguments, argv[1]);
HANDLE proc = OpenProcess(PROCESS_ALL_ACCESS, FALSE, pid);
LPVOID remote_tramp = VirtualAllocEx(proc, NULL, 0x1000, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);
LPVOID remote_args = (LPVOID)((DWORD)remote_tramp + size_tramp);
*(DWORD*)(&shellcode_tramp[6]) = (DWORD)remote_args;
WriteProcessMemory(proc, remote_tramp, shellcode_tramp, size_tramp, NULL); // Write the trampoline
WriteProcessMemory(proc, remote_args, arguments, strlen(arguments), NULL); // Write the arguments
BYTE firstCall[] = "\xE8\x00\x00\x00\x00\x90";
BYTE secondCall[] = "\xE8\x00\x00\x00\x00\x90";
*(DWORD*)(&firstCall[1]) = (DWORD)remote_tramp - 0x4012E1 - 5;
*(DWORD*)(&secondCall[1]) = (DWORD)remote_tramp - 0x40145B - 5;
WriteProcessMemory(proc, (LPVOID)0x4012E1, firstCall, 6, NULL); // Write first detour call
WriteProcessMemory(proc, (LPVOID)0x40145B, secondCall, 6, NULL); // Write second detour call
CloseHandle(proc);
return 0;
}
UINT WINAPI EzGetPid(LPCSTR procName, UINT *pid, UINT size)
{
HANDLE hSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
PROCESSENTRY32 buffer = {0};
buffer.dwSize = sizeof(PROCESSENTRY32);
UINT count = 0;
while (Process32Next(hSnap, &buffer) && count < size) {
if (!strcmp(buffer.szExeFile, procName))
pid[count++] = buffer.th32ProcessID;
}
CloseHandle(hSnap);
return count;
}
p.s. I added the last closed bracket as I thought I may have copied it wrong when I copied it long ago.
Do I need to use the Visual Studios interface to do this? I was wondering if someone that knows C could look at the code I'm trying to compile and help explain anything I am missing or any special instructions as to how to run it.
Thank you very much for all help.
Your program requires arguments in order to run correctly. The reason you're program doesn't do anything is because when double clicking it, you're not passing any arguments. The console is closing before you see the debug message "You must specifie the arguments".
Typically it's much easier to deal with trampoline hooks using an internal injected DLL method rather than this external method. You could start the process in a suspended state then inject your DLL to perform the trampoline hook. Then you can easily modify the function arguments of the function you're hooking.
Here is the code I use for x86 trampoline hooks
bool Detour32(BYTE* src, BYTE* dst, const uintptr_t len)
{
if (len < 5) return false;
DWORD curProtection;
VirtualProtect(src, len, PAGE_EXECUTE_READWRITE, &curProtection);
uintptr_t relativeAddress = dst - src - 5;
*src = 0xE9;
*(uintptr_t*)(src + 1) = relativeAddress;
VirtualProtect(src, len, curProtection, &curProtection);
return true;
}
BYTE* TrampHook32(BYTE* src, BYTE* dst, const uintptr_t len)
{
if (len < 5) return 0;
//Create Gateway
BYTE* gateway = (BYTE*)VirtualAlloc(0, len, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);
//write the stolen bytes to the gateway
memcpy_s(gateway, len, src, len);
//Get the gateway to destination address
uintptr_t gatewayRelativeAddr = src - gateway - 5;
// add the jmp opcode to the end of the gateway
*(gateway + len) = 0xE9;
//Write the address of the gateway to the jmp
*(uintptr_t*)((uintptr_t)gateway + len + 1) = gatewayRelativeAddr;
//Perform the detour
Detour32(src, dst, len);
return gateway;
}
Here is an example of how I use it to took OpenGL's SwapBuffers function, in this example we will change the hDc argument to 1337.
typedef BOOL(__stdcall* twglSwapBuffers) (HDC hDc);
twglSwapBuffers owglSwapBuffers;
BOOL __stdcall hkwglSwapBuffers(HDC hDc)
{
hDc = 1337;
return owglSwapBuffers(hDc);
}
owglSwapBuffers = (twglSwapBuffers)mem::TrampHook32((BYTE*)owglSwapBuffers, (BYTE*)hkwglSwapBuffers, 5);

Process POST data in microhttp server in C

I have the following code to process the POST data in the microhttp server:
#include <microhttpd.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <stdbool.h>
#define PAGE "<html><head><title>libmicrohttpd demo</title>"\
"</head><body>libmicrohttpd demo!!</body></html>"
struct postStatus {
bool status;
char *buff;
};
static int ahc_echo(void * cls,
struct MHD_Connection * connection,
const char * url,
const char * method,
const char * version,
const char * upload_data,
size_t * upload_data_size,
void ** ptr) {
const char * page = cls;
struct MHD_Response * response;
int ret;
struct postStatus *post = NULL;
post = (struct postStatus*)*ptr;
if(post == NULL) {
post = malloc(sizeof(struct postStatus));
post->status = false;
*ptr = post;
}
if(!post->status) {
post->status = true;
return MHD_YES;
} else {
if(*upload_data_size != 0) {
post->buff = malloc(*upload_data_size + 1);
snprintf(post->buff, *upload_data_size,"%s",upload_data);
*upload_data_size = 0;
return MHD_YES;
} else {
printf("Post data: %s\n",post->buff);
free(post->buff);
}
}
if(post != NULL)
free(post);
response = MHD_create_response_from_buffer (strlen(page),
(void*) page,
MHD_RESPMEM_PERSISTENT);
ret = MHD_queue_response(connection,
MHD_HTTP_OK,
response);
MHD_destroy_response(response);
return ret;
}
int main(int argc,
char ** argv) {
struct MHD_Daemon * d;
d = MHD_start_daemon(MHD_USE_SELECT_INTERNALLY,
9000,
NULL,
NULL,
&ahc_echo,
PAGE,
MHD_OPTION_END);
if (d == NULL)
return 1;
sleep(10000);
MHD_stop_daemon(d);
return 0;
}
I try the following CURL command to test the POST data processing:
curl -XPOST -d '{"email":"test#gmail.com","password":"test"}' 'http://192.168.1.17:9000'
But I get the output {"email":"test#gmail.com","password":"test". I don't get the last }. I tried larger length json inputs also. Still the same. Can't get the last curly brace. Can somebody please help out?
Thanks
EDIT: I got it working. I used strncpy(post->buff, upload_data, *upload_data_size) instead of snprintf.
Could someone please explain why didn't snprintf work?
ahc_echo() will be called at least two times for the request. The request data might be split up into multiple calls, and this fragmentation is very random (depends on how that request is buffered, and what each read() call on the socket returns). So your current code will only work with small requests, but are still unsafe.
MHD_create_post_processor() is a helper for parsing this partial buffers.
https://www.gnu.org/software/libmicrohttpd/tutorial.html#Processing-POST-data goes throught this
The reason
snprintf(post->buff, *upload_data_size,"%s",upload_data);
does not work, is that it should have been
snprintf(post->buff, *upload_data_size + 1,"%s",upload_data);
in order to match the memory size used in malloc(), which has room for the \0 termination.
strncpy(post->buff, upload_data, *upload_data_size);
Is actually dangerous, since it should have been
strncpy(post->buff, upload_data, *upload_data_size);
post->buff[*upload_data_size] = 0;
Since you need to make sure the result is zero terminated (it is just lucky that memory contains a zero already now, this is random behaviour when using malloc(), and not calloc()), and increasing the copy size to *upload_data_size + 1 would be wrong, since that would overflow the source by one byte, which also contains random data, or maybe even invalid memory.

My Program Keeps Failing With - Error While Loading Shared Libraries

I wrote a program "run_coffee.c" to implement fork() and exec() system calls. It fundamentally calls exec to start another process "coffee" built through "coffee.c" multiple times. The problem is I am running this program on cygwin64 in windows environment and it keeps failing with the following error -
**
error while loading shared libraries: ?: cannot open shared object
file: no such file or directory
**
I also ran cygcheck to see wether dependencies are being met or not. This is the output -
C:\cygwin64\home\Admin\run_coffee.exe C:\cygwin64\bin\cygwin1.dll
C:\Windows\system32\KERNEL32.dll
C:\Windows\system32\API-MS-Win-Core-RtlSupport-L1-1-0.dll
C:\Windows\system32\ntdll.dll C:\Windows\system32\KERNELBASE.dll
C:\Windows\system32\API-MS-Win-Core-ProcessThreads-L1-1-0.dll
C:\Windows\system32\API-MS-Win-Core-Heap-L1-1-0.dll
C:\Windows\system32\API-MS-Win-Core-Memory-L1-1-0.dll
C:\Windows\system32\API-MS-Win-Core-Handle-L1-1-0.dll
C:\Windows\system32\API-MS-Win-Core-Synch-L1-1-0.dll
C:\Windows\system32\API-MS-Win-Core-File-L1-1-0.dll
C:\Windows\system32\API-MS-Win-Core-IO-L1-1-0.dll
C:\Windows\system32\API-MS-Win-Core-ThreadPool-L1-1-0.dll
C:\Windows\system32\API-MS-Win-Core-LibraryLoader-L1-1-0.dll
C:\Windows\system32\API-MS-Win-Core-NamedPipe-L1-1-0.dll
C:\Windows\system32\API-MS-Win-Core-Misc-L1-1-0.dll
C:\Windows\system32\API-MS-Win-Core-SysInfo-L1-1-0.dll
C:\Windows\system32\API-MS-Win-Core-Localization-L1-1-0.dll
C:\Windows\system32\API-MS-Win-Core-ProcessEnvironment-L1-1-0.dll
C:\Windows\system32\API-MS-Win-Core-String-L1-1-0.dll
C:\Windows\system32\API-MS-Win-Core-Debug-L1-1-0.dll
C:\Windows\system32\API-MS-Win-Core-ErrorHandling-L1-1-0.dll
C:\Windows\system32\API-MS-Win-Core-Fibers-L1-1-0.dll
C:\Windows\system32\API-MS-Win-Core-Util-L1-1-0.dll
C:\Windows\system32\API-MS-Win-Core-Profile-L1-1-0.dll
C:\Windows\system32\API-MS-Win-Security-Base-L1-1-0.dll
No error or unmet dependency showed up so I guess all dependencies are being met. So what is causing this problem? Please Help.
Here are the two programs -
coffee.c
#include<stdio.h>
#include<stdlib.h>
int main(int argc, char *argv[])
{
char *w = getenv("EXTRA");
if (!w)
w = getenv("FOOD");
if (!w)
w = argv[argc-1];
char *c = getenv("EXTRA");
if (!c)
c = argv[argc-1];
printf("%s with %s\n", c, w);
return 0;
}
run_coffee.c
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
struct food_options
{
char *food;
char *extra;
};
int main()
{
int i;
char **env;
env[0] = (char*)malloc(sizeof(char) * 20);
env[1] = (char*)malloc(sizeof(char) * 20);
env[2] = (char*)malloc(sizeof(char) * 20);
struct food_options *opts = (struct food_options *)malloc(sizeof(struct food_options) * 3);
opts[0].food = "coffee";
opts[0].extra = "donuts";
opts[1].food = "fish";
opts[1].extra = "chips";
opts[2].food = "kabab";
opts[2].extra = "parantha";
for (i = 0; i < 3; i++)
{
pid_t pid = fork();
if (pid == -1)
{
fprintf(stderr, "Cannot fork process. Fatal Error %s\n", strerror(errno));
return 1;
}
else if (!pid)
{
sprintf(env[0], "FOOD=%s", opts[0].food);
sprintf(env[1], "EXTRA=%s", opts[0].extra);
env[2] = NULL;
if (execle("coffee.exe","coffee.exe",NULL,env) == -1)
{
fprintf(stderr, "Cannot execute coffee.exe. Error %s\n", strerror(errno));
}
}
}
free(opts);
free(env[0]);
free(env[1]);
free(env[2]);
return 0;
}
There is a memory bug in your program which can cause undefined behavior: you declared env to be an array of char*'s, but you did not initialize env. Hence, env[0], env[1], and env[2] point to random locations in memory. When you do sprintf(env[0], ...) and sprintf(env[1], ...), you are writing data to some random location in memory (where ever env[0] and env[1] points to). This can cause almost anything to happen, including modification of the names of libraries, making you unable to load them.

called library procedure is running in infinity cycle on gnu/linux

I've got an library which must read data from sqlite database by calling
extern int read(char** argv, int argc); // from header
it must process:
int read(char** argv, int argc) {
char* lineborder1;
char* lineborder2;
char* spaces1;
char* spaces2;
int maxl2 = 0, maxl1 = 0;
int i, maxi1, maxi2;
if (prelude() == -1) return -1;
// etc...
where prelude is inner procedure for sqlite connection:
int prelude() {
timefile = 0;
f = NULL;
#ifndef WIN32
char* temp = (char*)calloc(200, sizeof(char));
#endif
queries = (char**)malloc(sizeof(char*) * q_cnt);
for (x = 0; x < q_cnt; x++) {
queries[x] = (char*)malloc(sizeof(char) * q_size);
}
#ifdef WIN32
retval = sqlite3_open("todo.db3", &handle);
#else
home = (char*)getenv("HOME");
strcpy(temp, home);
retval = sqlite3_open(strcat(temp, "/.todo.db3"), &handle);
free(temp);
#endif
if (retval) {
printf("Database connection failed\n\r");
return -1;
}
return 0;
}
whole source is here : bitbucket: ctodo.c
I call this read from my application:
else if ((strcmp(argv[1], "read") == 0) || (strcmp(argv[1], "r") == 0)) {
return read(argv, argc);
but getting infinity cycle of this read call:
>>./todo r
Database connection failed
Database connection failed
Database connection failed
.... etc
here is how do I build it:
gcc -I . -c -o todo.a ctodo.c -lsqlite3 -O3
gcc -I . -o todo cctodo.c -lsqlite3 -O3 todo.a
help or version calls wrok fine and read works fine on windows, something specific to my linux build is here but I can't find a bug so far. what could call this read to run in infinity cycle like that?
The read function is defined in libc.so, and used to, you know, read data.
It is exceedingly likely that sqlite3_open() calls it.
By introducing your own function called read(), you've made your program enter infinite loop. If you wait long enough, your program will run out of stack and crash.
Doctor, it hurts when I do that. Well, don't do that :-)

tinyc compiler - libtcc, how to bound check?

im using libtcc to compile c code on the fly. Im going to use it on a cloud computer, to be used over the internet.
how do i use tinyc's built in memory and bound checker function?
heres an example that comes with the tinyc libtcc library?
any help would be great!
thank you!
/*
* Simple Test program for libtcc
*
* libtcc can be useful to use tcc as a "backend" for a code generator.
*/
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include "libtcc.h"
/* this function is called by the generated code */
int add(int a, int b)
{
return a + b;
}
char my_program[] =
"int fib(int n)\n"
"{\n"
" if (n <= 2)\n"
" return 1;\n"
" else\n"
" return fib(n-1) + fib(n-2);\n"
"}\n"
"\n"
"int foo(int n)\n"
"{\n"
" printf(\"Hello World!\\n\");\n"
" printf(\"fib(%d) = %d\\n\", n, fib(n));\n"
" printf(\"add(%d, %d) = %d\\n\", n, 2 * n, add(n, 2 * n));\n"
" return 0;\n"
"}\n";
int main(int argc, char **argv)
{
TCCState *s;
int (*func)(int);
void *mem;
int size;
s = tcc_new();
if (!s) {
fprintf(stderr, "Could not create tcc state\n");
exit(1);
}
/* if tcclib.h and libtcc1.a are not installed, where can we find them */
if (argc == 2 && !memcmp(argv[1], "lib_path=",9))
tcc_set_lib_path(s, argv[1]+9);
/* MUST BE CALLED before any compilation */
tcc_set_output_type(s, TCC_OUTPUT_MEMORY);
if (tcc_compile_string(s, my_program) == -1)
return 1;
/* as a test, we add a symbol that the compiled program can use.
You may also open a dll with tcc_add_dll() and use symbols from that */
tcc_add_symbol(s, "add", add);
/* get needed size of the code */
size = tcc_relocate(s, NULL);
if (size == -1)
return 1;
/* allocate memory and copy the code into it */
mem = malloc(size);
tcc_relocate(s, mem);
/* get entry symbol */
func = tcc_get_symbol(s, "foo");
if (!func)
return 1;
/* delete the state */
tcc_delete(s);
/* run the code */
func(32);
free(mem);
return 0;
}
you can set bounds checking manually using:
s->do_bounds_check = 1; //s here is TCCState*
just make sure libtcc is compiled with CONFIG_TCC_BCHECK being defined.
you may also want to enable debugging using:
s->do_debug = 1;
the command line option -b does the exact same to enable bounds checking (it enables debugging as well).

Resources