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 :-)
Related
For compilation I used:
1) ./configure --enable-dddmp --enable-obj --enable-shared --enable-static; make
2) gcc test.c -o testprogram -I /path/to/cudd-3.0.0/cudd -I /path/to/cudd-3.0.0/util -I /path/to/cudd-3.0.0/ -static -L /path/to/cudd-3.0.0/cudd/.libs/ -lcudd -lm
The program is compiled successfully. I am using cudd3.0.0 package. After that I am getting this segmentation error in execution:
Please suggest the proper way to execute this and why I am getting this error?
I am adding the main function:
int main (int argc, char *argv[])
{
char filename[30];
DdManager *gbm; /* Global BDD manager. */
gbm = Cudd_Init(0,0,CUDD_UNIQUE_SLOTS,CUDD_CACHE_SLOTS,0); /* Initialize a new BDD manager. */
DdNode *bdd, *var, *tmp_neg, *tmp;
int i;
bdd = Cudd_ReadOne(gbm); /*Returns the logic one constant of the manager*/
Cudd_Ref(bdd); /*Increases the reference count of a node*/
for (i = 3; i >= 0; i--) {
var = Cudd_bddIthVar(gbm,i); /*Create a new BDD variable*/
tmp_neg = Cudd_Not(var); /*Perform NOT boolean operation*/
tmp = Cudd_bddAnd(gbm, tmp_neg, bdd); /*Perform AND boolean operation*/
Cudd_Ref(tmp);
Cudd_RecursiveDeref(gbm,bdd);
bdd = tmp;
}
bdd = Cudd_BddToAdd(gbm, bdd); /*Convert BDD to ADD for display purpose*/
print_dd (gbm, bdd, 2,4); /*Print the dd to standard output*/
sprintf(filename, "./bdd/graph.dot"); /*Write .dot filename to a string*/
write_dd(gbm, bdd, filename); /*Write the resulting cascade dd to a file*/
Cudd_Quit(gbm);
return 0;
}
Yes, It is resolved. I have not made the folder named 'bdd' in the proper location for the code line:
sprintf(filename, "./bdd/graph.dot");
Now, it is executing. Sorry, I thought it was some conceptual error.
Even though we set currentMethod.bytes with local function to generate random numbers, the RAND_bytes is not invoking. After we set RAND_set_rand_method(&cuurentMethod).
Here I attached link [https://github.com/openssl/openssl/blob/master/test/sm2_internal_test.c] which I already tried.
int main()
{
unsigned char rand[16];
int ret;
RAND_METHOD *oldMethod,currentMethod,*temp;
oldMethod = RAND_get_rand_method();/*getting default method*/
currentMethod = *oldMethod;
currentMethod.bytes = local_function_rand;
if((ret = RAND_set_rand_method(¤tMethod))!= 1)
return 0;
/* Now we are printing both address of local_function_method_rand() and
temp->bytes , those address are same after getting. */
temp = RAND_get_rand_method();
/* after we are comparing with RAND_SSLeay() function , to find default or not*/
if((ret = RAND_bytes(rand,16)) != 1)
return 0;
return 1;
}
Expecting result is our local function should invoke. Also, to invoke RAND_bytes() is it required to set fips mode in Linux system?
After cleaning up and minimizing your test program and filling in the missing parts:
#include <openssl/rand.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int local_function_rand(unsigned char *buf, int num) {
printf("in local_function_rand(); requested %d bytes\n", num);
memset(buf, 4, num); // RFC 1149.5 standard random number
return 1;
}
int main(void) {
unsigned char rand[16];
RAND_METHOD currentMethod = {.bytes = local_function_rand};
RAND_set_rand_method(¤tMethod);
if (RAND_bytes(rand, sizeof rand) != 1) {
return EXIT_FAILURE;
}
return 0;
}
and running it (With OpenSSL 1.1.1):
$ gcc -Wall -Wextra rand.c -lcrypto
$ ./a.out
in local_function_rand(); requested 16 bytes
it works as expected; the user-supplied function is being called by RAND_bytes(). If you're getting different results from your code, there's probably a problem in the bits you didn't include in your question.
I wish to use a c program repeatedly run the TCL interpreter many times. For reasons that are complicated, I need this to be a pure C program and not something that is embedded as a shared object. As an example, I wish to run this simple tcl program, tryMe.tcl, twice:
prtstr "Test from tryMe.tcl"
The prtstr is a TCL function that I have written that for right now just writes to stdout. Below is the c code that is attempting to interpret the tryMe.tcl program twice.
I compile the program below like this under linux:
$ gcc -c try.c; gcc -o try try.o -ltcl;
and run it like this:
$ ./try tryMe.tcl
And I get zero output. What am I doing wrong? Also are there steps required to reset the tcl interpreter so that it will be fresh each time.
#define _GNU_SOURCE
#include <tcl/tcl.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int PrintStrObjCmd(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])
{
char *str;
int len;
Tcl_Obj *objPtr;
int i;
if (objc != 2) {
Tcl_WrongNumArgs(interp, 1, objv, "value");
return TCL_ERROR;
}
objPtr = objv[1];
str = Tcl_GetStringFromObj(objPtr, &len);
if (str[0] == '\0')
return TCL_ERROR;
printf("len: %d, str: %s\n", len, str);
return TCL_OK;
}
int Tcl_AppInit(Tcl_Interp* interp)
{
if (Tcl_Init(interp) == TCL_ERROR)
return TCL_ERROR;
Tcl_CreateObjCommand(interp,"prtstr", PrintStrObjCmd, (ClientData) NULL, (Tcl_CmdDeleteProc *) NULL);
return TCL_OK;
}
int main(int argc, char *argv[])
{
char *cmd = NULL;
Tcl_Interp * interp = Tcl_CreateInterp();
Tcl_AppInit(interp);
asprintf(&cmd, "%s -x -y -z", argv[1]);
Tcl_Eval(interp, cmd);
free(cmd);
asprintf(&cmd, "%s -q -r -s 2", argv[1]);
Tcl_Eval(interp, cmd);
exit(0);
}
Thanks very much!
You should check out the Tcler's Wiki on this, as the pattern of embedding a Tcl interpreter in your application is a known and supported one. It includes a worked example that you can adapt (and no, I didn't write it; I prefer to extend standard Tcl interpreters).
The main problem you've got is that you're not calling Tcl_FindExecutable(). In modern Tcl, that initialises a number of key subsystems in the library (including its high-performance memory allocator!) so it's slightly vital. In your case, you've got a real argv available so you can use argv[0] with it:
Tcl_FindExecutable(argv[0]);
// NULL would also work as an argument, in a pinch at least
Once you've done that, you can call other Tcl API functions, specifically Tcl_CreateInterp().
You have a minor problem in that you are not testing the results of calls for failure. In C, this is essential as you don't have exceptions to do the heavy lifting of error handling for you.
Thanks for the pointer to TCLer's Wiki. That helped. I didn't understand that the script in Tcl_Eval(interp,script) was not a file name but a character string containing a tcl program. So this program uses TCL_Evalfile() I also wanted to be able to pass command line arguments to the tcl program. I found out how but diving into the TCL source for Tcl_MainEx(). Below is a program that does what I want. Also I discovered that calling Tcl_EvalFile more than one does retains the state so if I want a fresh value of the interpreter, I'll have to delete the old one and create a new one everytime.
#include <tcl/tcl.h>
#include <stdio.h>
#include <stdlib.h>
int PrintStrObjCmd(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])
{
char *str;
int len;
Tcl_Obj *objPtr;
int i;
if (objc != 2) {
Tcl_WrongNumArgs(interp, 1, objv, "value");
return TCL_ERROR;
}
objPtr = objv[1];
str = Tcl_GetStringFromObj(objPtr, &len);
if (str[0] == '\0')
return TCL_ERROR;
printf("len: %d, str: %s\n", len, str);
return TCL_OK;
}
int Tcl_AppInit(Tcl_Interp* interp)
{
if (Tcl_Init(interp) == TCL_ERROR)
return TCL_ERROR;
Tcl_CreateObjCommand(interp,"prtstr", PrintStrObjCmd, (ClientData) NULL, (Tcl_CmdDeleteProc *) NULL);
return TCL_OK;
}
int main(int argc, char **argv)
{
char *script = argv[1];
Tcl_Obj *argvPtr;
Tcl_FindExecutable(script);
Tcl_Interp *interp = Tcl_CreateInterp();
if (interp == NULL) {
fprintf(stderr,"Cannot create TCL interpreter\n");
exit(-1);
}
if (Tcl_AppInit(interp) != TCL_OK)
return TCL_ERROR;
Tcl_SetVar2Ex(interp, "argv0", NULL, Tcl_NewStringObj(script,-1), TCL_GLOBAL_ONLY);
argc -= 2;
argv += 2;
Tcl_SetVar2Ex(interp, "argc", NULL, Tcl_NewIntObj(argc), TCL_GLOBAL_ONLY);
argvPtr = Tcl_NewListObj(0, NULL);
while (argc--)
Tcl_ListObjAppendElement(NULL, argvPtr, Tcl_NewStringObj(*argv++, -1));
Tcl_SetVar2Ex(interp, "argv", NULL, argvPtr, TCL_GLOBAL_ONLY);
if (Tcl_EvalFile(interp, script) != TCL_OK)
return TCL_ERROR;
exit(0);
}
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.
The Linux specific backtrace() and backtrace_symbols() allows you to produce a call trace of the program. However, it only prints function addresses, not their names for my program. How can I make them print the function names as well ? I've tried compiling the program with -g as well as -ggdb. The test case below just prints this:
BACKTRACE ------------
./a.out() [0x8048616]
./a.out() [0x8048623]
/lib/libc.so.6(__libc_start_main+0xf3) [0x4a937413]
./a.out() [0x8048421]
----------------------
I'd want the first 2 items to also show the function names, foo and main
Code:
#include <execinfo.h>
#include <string.h>
#include <errno.h>
#include <unistd.h>
#include <stdlib.h>
static void full_write(int fd, const char *buf, size_t len)
{
while (len > 0) {
ssize_t ret = write(fd, buf, len);
if ((ret == -1) && (errno != EINTR))
break;
buf += (size_t) ret;
len -= (size_t) ret;
}
}
void print_backtrace(void)
{
static const char start[] = "BACKTRACE ------------\n";
static const char end[] = "----------------------\n";
void *bt[1024];
int bt_size;
char **bt_syms;
int i;
bt_size = backtrace(bt, 1024);
bt_syms = backtrace_symbols(bt, bt_size);
full_write(STDERR_FILENO, start, strlen(start));
for (i = 1; i < bt_size; i++) {
size_t len = strlen(bt_syms[i]);
full_write(STDERR_FILENO, bt_syms[i], len);
full_write(STDERR_FILENO, "\n", 1);
}
full_write(STDERR_FILENO, end, strlen(end));
free(bt_syms);
}
void foo()
{
print_backtrace();
}
int main()
{
foo();
return 0;
}
The symbols are taken from the dynamic symbol table; you need the -rdynamic option to gcc, which makes it pass a flag to the linker which ensures that all symbols are placed in the table.
(See the Link Options page of the GCC manual, and / or the Backtraces page of the glibc manual.)
Use the addr2line command to map executable addresses to source code filename+line number. Give the -f option to get function names as well.
Alternatively, try libunwind.
The excellent Libbacktrace by Ian Lance Taylor solves this issue. It handles stack unwinding and supports both ordinary ELF symbols and DWARF debugging symbols.
Libbacktrace does not require exporting all symbols, which would be ugly, and ASLR does not break it.
Libbacktrace was originally part of the GCC distribution. Now, a standalone version can be found on Github:
https://github.com/ianlancetaylor/libbacktrace
the answer on the top has a bug
if ret == -1 and errno is EINTER you should try again, but not count ret as copied
(not going to make an account just for this, if you don't like it tough)
static void full_write(int fd, const char *buf, size_t len)
{
while (len > 0) {
ssize_t ret = write(fd, buf, len);
if ((ret == -1) {
if (errno != EINTR))
break;
//else
continue;
}
buf += (size_t) ret;
len -= (size_t) ret;
}
}
Boost backtrace
Very convenient because it prints both:
unmangled C++ function names
line numbers
automatically for you.
Usage summary:
#define BOOST_STACKTRACE_USE_ADDR2LINE
#include <boost/stacktrace.hpp>
std::cout << boost::stacktrace::stacktrace() << std::endl;
I have provided a minimal runnable example for it and many other methods at: print call stack in C or C++