protoc-c: Nested structure with optional string throws seg fault - c

Trying out Google protocol buffers for my code in C language.
messagefile.proto
===================
mesage othermessage
{
optional string otherstring = 1;
}
message onemessage
{
optional string messagestring = 1;
optional int32 aninteger = 2;
optional othermessage otr_message= 3;
}
==============================================
--> protoc-c messagefile.proto --c_out=./
this resulted in two files
--> messagefile.pb-c.c and messagefile.pb-c.h
Now my code file which would try to use the
simpleexample.c
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include "messagefile.pb-c.h"
#include <stdbool.h>
int main(int argc, const char * argv[])
{
onemessage msg = ONE__MESSAGE__INIT; //from generated .h code file
void *buf;
unsigned int len;
char *ptr;
//integer initialization
msg.has_aninteger = true;
msg.aninteger = 1;
//accessing the string in onemessage
msg.messagestring = malloc(sizeof("a simple string"));
strncpy(msg.messagestring,"a simple string",strlen("a simple string"));
//trying to initialize the string in the nested structure othermessage
msg.otr_message = malloc(sizeof(othermessage));
msg.otr_message->otherstring = malloc(sizeof("a not so simple string"));
strncpy(msg.otr_message->otherstring,"a not so simple string",strlen("a not so simple string"));
//lets find the length of the packed structure
len = one_message__get_packed_size(&msg); //from generated .h code
//lets arrange for as much size as len
buf = malloc(len);
//lets get the serialized structure in buf
one_message__pack_to_buffer(&msg,buf); //from generated code
//write it to a stream, for now the screen
fwrite(buf,len,1,stdout);
//free buffer
free(buf);
return 0;
}
I compile it as gcc -o testout messagefile.pb-c.c simpleexample.c -lprotobuf-c
The Problem I am facing is when trying to initialize the nested othermessage variables and then call the get_packed_size it throws a segmentation fault.
I tried various combinations and I can say that whenever having strings in a nested class, I am facing problem to access those using google protoc.
Am i missing something? Is there anything wrong.
Can anyone please help.
note:There might be a few general syntax errors please ignore them.
ThankYou.

note:There might be a few general syntax errors please ignore them.
Err... they are kinda hard to ignore since your code does not compile :-)
Anyway, apart from the syntax errors, you need to make several corrections to your code. In order to use the field otr_message, it is not sufficient to just malloc() it. You also need to initialize it so the headers in the message get the right values. This is done with init(), like this:
//trying to initialize the string in the nested structure othermessage
msg.otr_message = malloc(sizeof(othermessage));
othermessage__init(msg.otr_message);
Then you use the wrong function to do the packing to your own array. As explained here, you need to use pack() as opposed to pack_to_buffer(), like this:
//lets get the serialized structure in buf
onemessage__pack(&msg,buf); //from generated code
Finally, your strncpy() invocations have a mistake. The length calculated with strlen() does not include the null terminator, which you do need. So you need to take strlen()+1 or use sizeof(), like this:
strncpy(msg.messagestring,"a simple string",sizeof("a simple string"));
After making those changes, the example worked for me:
$ ./testout
a simple string
a not so simple string

Related

SWIG convert C-Pointer stringvalue to tcl string

because of my limited knowledge in C and SWIG i couldn't manage to adopt any public example for converting c-pointer chars to tcl strings ....
I always get stuck at the problem that my tcl variable just doesn't get dereferenced
like this :
tcl_str = _30e84c05ef550000_p_stringout2
string_pointer.c
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <time.h>
#include "string_pointer.h"
stringout2 Itla_Get_Model_Version (int laser, char * mv_string)
{
stringout2 * pointer2;
char *mod_ver ="PPCL600";
pointer2 = malloc( sizeof(stringout2) );
pointer2-> modelvers= *mod_ver;
printf ( "Itla_Get_Model_Version : read %s \n", mod_ver );
return *pointer2 ;
}
string_pointer.h
#include <sys/types.h>
#include <sys/resource.h>
typedef struct {
char * modelvers;
} stringout2;
stringout2 Itla_Get_Model_Version (int laser, char * mv_string) ;
string_pointer.swig
/* File : string_pointer.swig */
%module string_pointer
%{
#include "string_pointer.h"
%}
%include "typemaps.i"
%include "cpointer.i"
%include "cstring.i"
%typemap(argout) char* (char tmp) %{
$1 = &tmp;
%}
stringout2 Itla_Get_Model_Version (int laser, char *OUTPUT) ;
%include "string_pointer.h"
test.tcl
load ./string_pointer.so
proc test { laser } {
scan [Itla_Get_Model_Version $laser ] %s a
puts "$a "
return $a
}
set name [test 1 ]
puts "Itla_Get_Model_Version= $name"
when executing the tcl-script you get :
Itla_Get_Model_Version : read PPCL600
_f0a759f8d9550000_p_stringout2
Itla_Get_Model_Version= _f0a759f8d9550000_p_stringout2
so i finally need to dereference the Pointer to its value ...
But i don't know how to succeed.....
The C-function is given and can't be modified !
Anybody out there, knowing how to do it ?
If your strings are basically ASCII or UTF-8, all you need to do is to tell SWIG that your function has allocated the string it is returning. For details see, the SWIG docs on C strings.
yourcode.c
char *Itla_Get_Model_Version (int laser, char * mv_string) {
// I assume this is a proxy for something more complicated...
const char *mod_ver ="PPCL600";
size_t len = strlen(mod_ver) + 1;
char *output = malloc(len);
memcpy(output, mod_ver, len);
printf ( "Itla_Get_Model_Version : read %s \n", mod_ver );
return output;
}
yourcode.h
char *Itla_Get_Model_Version(int laser, char * mv_string);
yourcode.swig
/* Tell SWIG that this function returns something to be freed */
%newobject Itla_Get_Model_Version
/* And now we can use the standard C header */
%include "yourcode.h"
If the above simple solution doesn't work…
Things get a lot more complicated if you are using a different encoding for your strings or if you wrap them inside a structure (as you did in your question). That's when you need a typemap, particularly ones of the Tcl variety. Correctly writing a typemap depends on understanding the semantics of the values that you are producing and/or consuming and the semantics of the language that you're using. Assuming you want the wrapping, here's a very simple output typemap that might work:
%typemap(out) stringout2* {
Tcl_SetObjResult(interp, Tcl_NewStringObj($1->modelvers, -1));
free($1);
}
Your function also needs to be modified to return a stringout2* by doing return pointer2;, and not a stringout2 since otherwise you will be leaking memory on every call. You can return a stringout2, but if you are doing that then you should not allocate it with malloc, but rather keep it as a structure directly in a local variable.
In that case, the typemap you'd use is:
%typemap(out) stringout2 {
Tcl_SetObjResult(interp, Tcl_NewStringObj($1.modelvers, -1));
}
(Note the different type, different access to the field, and lack of free.)
And your structure should be declared as containing a const char * if it really is that.
If you have strings in a different encoding (and it isn't ISO 8859-1, for which you can cheat and use a binary string using Tcl_NewByteArrayObj; that's also what you want for slabbing a chunk of binary data over) then you'll need to write a typemap using Tcl_ExternalToUtfDString, and the amount of boilerplate code goes up. Tcl insists that its internal strings are in (almost) UTF-8, and ASCII is OK too as that's a strict subset; everything else must be converted.
Ask another question if that's what you need. You probably are either dealing with ASCII or binary data, so I'll leave (quite a bit more complex!) encoding conversion alone until requested.

Creating array of strings works in source code doesn't work in executable

I've got some code which generates an array of strings of different file names and then
passes them into a function to write some data to them. It adds a incrementing number to the starting filename which is supplied from an input argument.
The problem is that it works fine running from source in Visual Studio 2012 but when I compile it and run it as an .exe the program crashes.
The .exe doesn't appear to be passing the array of strings properly which is causing an error when it attempts to use the string
for opening a file etc.
Here is the isolated bit of code
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <math.h>
#include <string.h>
#include <stdint.h>
#include <Windows.h>
void processing_function(int num_output, char **outnames)
{
/* in Visual Studio this works fine and prints all
the names correctly. Running from .exe will crash */
for(int idx = 0; idx <num_output;idx++)
{
printf("outnames[%d] is %s\n",idx,outnames[idx]);
}
}
int main(int argc, char *argv[])
{
/*nframes comes from another function, outname comes from input arguement */
int num_output = ceil(((double)*nframes / 1100));
int outname_len = strlen(outname)+1;
char *out_right;
out_right = (char*) malloc(sizeof(char)*outname_len);
/*Split string to append numbers before file extension */
strcpy(out_right,outname);
strrev(out_right);
strtok(out_right,".");
strcat(out_right,".");
strrev(out_right);
int out_right_len = strlen(out_right);
strtok(outname,".");
strcat(outname,"-");
int out_origlen = strlen(outname);
int num_len = 1;
char **outnames;
char *num;
char *outname_tmp;
outnames = (char**) malloc(sizeof(char)*(num_output));
int out_len;
double dbl_idx;
int *numfs = (int*)malloc(sizeof(int)*num_output);
for(int idx = 1;idx <num_output+1;idx++)
{
/*convert output number to string and stitch complete name back together and place into array */
num_len = ceil(log10((double)idx+0.1));
num = (char*) malloc(sizeof(char)*(num_len+1));
outname_tmp = (char*) malloc(sizeof(char)*(out_origlen+num_len+out_right_len+1));
strcpy(outname_tmp,outname);
sprintf(num,"%d",idx);
strcat(outname_tmp,num);
free(num);
strcat(outname_tmp,out_right);
outnames[idx-1] = (char*) malloc(sizeof(char)*(out_origlen+num_len+out_right_len+1));
strcpy(outnames[idx-1],outname_tmp);
free(outname_tmp);
printf("%s\n",outnames[idx-1]);
}
free(out_right);
processing_function(num_ouput, outnames)
return(0);
}
EDIT: Changed num_input to num_output as they do have the same value.
Running from .exe will sometimes start printing some of the names and then crash, opening the
debugger gives an error within output.c, with an access reading violation. I tried putting this code at
the top of the processing_function but that gave further problems downstream (heap corruption), which makes me think that the
code is messing up the memory but I can't see whats wrong with it, nor why it would work in VS but not as a .exe.
I could try and dodge the issue by generating the next output name on the fly every time it requires one but I'd really rather know why this isn't working.
Any help would be greatly appreciated.
I am going to take a shot and say, you passed num_input to processing_function() with outnames, outnames was allocated with num_output for size, but num_input and num_output have different values at runtime. So that lets processing_function() access out of bounds.

Why's _itoa causing my program to crash?

The following code just keeps on crashing when it reaches the part with _itoa, I've tried to implement that function instead and then it got even weirder, it just kept on crashing when I ran it without the debugger but worked fine while working with the debugger.
# include "HNum.h"
# include <stdio.h>
# include <stdlib.h>
# include <string.h>
# include <assert.h>
# define START_value 30
typedef enum {
HNUM_OUT_OF_MEMORY = -1,
HNUM_SUCCESS = 0,
} HNumRetVal;
typedef struct _HNum{
size_t Size_Memory;
char* String;
}HNum;
HNum *HNum_alloc(){
HNum* first = (HNum*)malloc(sizeof(HNum));
if(first==NULL){
return NULL;
}
first->String =(char*)malloc(sizeof(START_value));
if(first->String==NULL){
return NULL;
}
first->Size_Memory = START_value; // slash zero && and starting from zero index;
return first;
}
HNumRetVal HNum_setFromInt(HNum *hnum, int nn){
itoa(nn,hnum->String,10);
}
void main(){
HNum * nadav ;
int h = 13428637;
nadav = HNum_alloc();
nadav->String="1237823423423434";
HNum_setFromInt(nadav,h);
printf("nadav string : %s \n ",nadav->String);
//printf("w string %s\n",w->String);
//printf("nadav string %s\n",nadav->String);
HNum_free(nadav);
}
I've been trying to figure this out for hours and couldn't come up with anything...
The IDE I'm using is Visual Studio 2012 express, the crash shows the following:
"PROJECT C.exe has stopped working
windows can check online for a solution to the program."
first->String =(char*)malloc(sizeof(START_value));
should be
first->String = malloc(START_value);
The current version allocates space for sizeof(int)-1 characters (-1 to leave space for the nul terminator). This is too small to hold your target value so _itoa writes beyond memory allocated for first->String. This results in undefined behaviour; it is quite possible for different runs to fail in different places or debug/release builds to behave differently.
You also need to remove the line
nadav->String="1237823423423434";
which leaks the memory allocated for String in HNum_alloc, replacing it with a pointer to a string literal. This new pointer should be considered to be read-only; you cannot write it it inside _itoa
Since I'm not allowed to comment:
simonc's answer is correct. If you find the following answer useful, you should mark his answer as the right one:P
I tried that code myself and the only thing missing is lets say:
strcpy(nadav->String, "1237823423423434"); INSTEAD OF nadav->String="1237823423423434";
and
first->String = malloc(START_value); INSTEAD OF first->String =(char*)malloc(sizeof(START_value));
Also, maybe you'd have to use _itoa instead of itoa, that's one of the things I had to change in my case anyhow.
If that doesn't work, you should probably consider using a different version of VS.

Linux kernel: why does this call to kstrtol crash?

I am learning kernel programming and have a simple call to kstrtol I am using to convert a string to a number. However, everytime I compile this module and use insmod to place it in the kernel, I get "BUG: unable to handle kernel paging request at f862b026" and then a register and stack dump.
I'm following the definition from here: https://www.kernel.org/doc/htmldocs/kernel-api/API-kstrtol.html. It seems like a really simple call. What am I doing wrong here?
#include <linux/kernel.h>
static int __init convert(void)
{
long myLong;
char *myNumber = "342";
myNumber[2] = '\0'; //Overwriting the '2', just so I know for sure I have a terminating '\0'
if (kstrtol(myNumber, 10, &myLong) == 0)
{
printk("We have a number!\n");
}
return 0;
}
static void __exit convert_exit(void)
{
printk("Module unloaded\n");
}
module_init(convert);
module_exit(convert_exit);
You cannot modify string literals. Copy it into an array firstly.
edit: use this instead
char mystr[] = "abdc";
edit2:
the underlying reason for this is, that a char pointer to a string literal points to a data segment, usually readonly. If you alter this memory you might get a crash.
When you create an array of chars instead, the string literal gets copied into the array on the stack, where you safely can modify it.

can't get C method icalrecur_expand_recurrence to work

This is a bit frustrating. I've been working on this for a while now, and I can't seem to get this method to work like it says it does.
#include "icalrecur.h"
#include <time.h> /* for time() */
#include <stdio.h>
int get_occurrences(char* rrule, time_t start, int count)
{
//char* rule; /* rule string */
// *rule = PG_GETARG_CHAR(0);
time_t *result[count]; /* output array */
icalrecur_expand_recurrence(rrule, start, count, *result);
return (time_t) *result;
}
//time_t *output[5*8];
void main() {
time_t right_now = time(0);
char *_rrule = "FREQ=WEEKLY;INTERVAL=2;COUNT=8;WKST=SU;BYDAY=TU,TH";
get_occurrences(_rrule, right_now, 5);
}
I save this test file as ical_recur.h. Then I type in bash:
gcc -I/usr/local/libical/include/libical -L/usr/local/libical/lib/ -lical -o hello ical_recur.c
To include the libical.a libraries. The include/libical directory has icalrecur.h in it, so I really don't even need to be including the whole ical library.
~: ./hello
Segmentation fault
Anytime I change around any pointers, it starts complaining about something during compilation. Can anyone get this to work?? Source files are from Marketcircle on github.
Looking at the documentation it seems that you have an unwanted extra level of indirection - you need to change:
time_t *result[count]; /* output array */
icalrecur_expand_recurrence(rrule, start, count, *result);
to:
time_t result[count]; /* output array */
icalrecur_expand_recurrence(rrule, start, count, result);
Also you're passing a read-only string literal to a function which expects a char * - this should at least give you a compiler warning (hint: always use gcc -Wall ..., read the warnings carefully, understand them and fix them). main() should look more like this:
int main() {
time_t right_now = time(0);
char _rrule[] = "FREQ=WEEKLY;INTERVAL=2;COUNT=8;WKST=SU;BYDAY=TU,TH";
get_occurrences(_rrule, right_now, 5);
return 0;
}
Some more problems:
this line doesn't do anything useful, but it's not clear what you're trying to achieve:
char _size = (char)(((int)'0') + sizeof(result));
all those casts are a "code smell" and this should tell you that you're doing something very wrong here
your function is defined as returning an int, but you're trying to cast your array to a time_t and return that, which also makes no sense - again, turn on compiler warnings - let the compiler help you find and fix your mistakes.
Now you can use this extension for postgresql.
Example usage:
SELECT * FROM
unnest(
rrule_get_occurrences('FREQ=WEEKLY;INTERVAL=1;WKST=MO;UNTIL=20200101T045102Z;BYDAY=SA;BYHOUR=10;BYMINUTE=51;BYSECOND=2'::rrule,
'2019-12-07 10:51:02+00'::timestamp with time zone)
);
unnest
------------------------
2019-12-07 10:51:02+00
2019-12-14 10:51:02+00
2019-12-21 10:51:02+00
2019-12-28 10:51:02+00
(4 rows)

Resources