my problem is that, just as I mentioned on the title, i have a function that, upon return, causes a SIGABRT to be raised. I ran valgrind on my program and I got this at that exact point.
==5807== Process terminating with default action of signal 6 (SIGABRT)
==5807== at 0x52F5428: raise (raise.c:54)
==5807== by 0x52F7029: abort (abort.c:89)
==5807== by 0x53377E9: __libc_message (libc_fatal.c:175)
==5807== by 0x53D911B: __fortify_fail (fortify_fail.c:37)
==5807== by 0x53D90BF: __stack_chk_fail (stack_chk_fail.c:28)
==5807== by 0x402E8B: foo (file.c:43)
==5807== by 0x202C27323939312C: ???
==5807== by 0x592D4D4D2D444426: ???
==5807== by 0x66202C2927595958: ???
==5807== by 0x2965736C60: ???
==5807== by 0x505770F: ??? (in /usr/lib/x86_64-linux-gnu/libodbc.so.2.0.0)
==5807==
This is the code i'm executing, the stack error causes the abort at the return ret statement from add_user:
int add_user(SQLHDBC dbc, char * mail, char * password, char * name, char * date) {
char query[TAM];
SQLHSTMT stmt;
SQLRETURN ret;
if (mail == NULL || password == NULL || name == NULL || date == NULL)
return ERR;
sprintf(query, "INSERT INTO mms_user values (default,'%s',encrypt_password('%s'),set_type(),'%s',to_date('%s', 'DD-MM-YYYY'), false)", mail, password, name,date);
ret= DBExecuteQuery(dbc, query, &stmt);
DBFreeHandle(&stmt);
return ret;
}
int DBExecuteQuery(SQLHDBC dbc, char * query, SQLHSTMT *stmt) {
SQLRETURN ret;
/*Error control*/
if (query == NULL || stmt == NULL)
return ERR;
/*Allocates memory for a new statement*/
ret = SQLAllocHandle(SQL_HANDLE_STMT, dbc, stmt);
if (!SQL_SUCCEEDED(ret)) {
return ERR;
}
/*Executes query and stores result in stmt*/
ret = SQLExecDirect(*stmt, (SQLCHAR *)query, SQL_NTS);
if (!SQL_SUCCEEDED(ret))
return ERR;
return OK;
}
int DBFreeHandle(SQLHSTMT * stmt){
int ret;
/*Frees allocated memory*/
ret = SQLFreeHandle(SQL_HANDLE_STMT, *stmt);
if (!SQL_SUCCEEDED(ret)) {
return ERR;
}
}
The function executes normally as far as I have checked. I don't know what could be happening, if any of you could provide any possible explanation, I would be really thankful. Also feel free to ask for further information (this is the only useful info I've been taught to look for, so I might need some guidance in that case).
Thank you in advance
This code is dangerous:
char query[TAM];
.
.
.
sprintf(query, "INSERT INTO mms_user values"
" (default,'%s',encrypt_password('%s'),set_type(),"
"'%s',to_date('%s', 'DD-MM-YYYY'), false)",
mail, password, name,date);
You do absolutely no bounds checking so it will overflow your stack easily.
Related
I am getting an unitialized warning in the following code, and I am stumped trying to figure out why.
I can't see a code path where it is used uninitialized.Can anyone please help?
Also, I could use some adivce on if my gotos are not used well or if there is a cleaner way of doing this.
In function ‘handle_comp_enc’:
fs/compress.c:101:8: warning: ‘write_cdata’ may be used uninitialized in this function [-Wmaybe-uninitialized]
kfree(write_cdata);
Code:
#define ENC (1UL << 1)
#define ZIP (1UL << 2)
#define ENC_ZIP_ENABLED(cmp_enc_flags) ((cmp_enc_flags) & (ENC | ZIP)) == (ENC | ZIP)
int handle_comp_enc(unsigned long comp_enc_flags, unsigned char *read_data,
size_t read_len, unsigned char *write_data, size_t *write_len2) {
unsigned char *write_cdata, *rd_enc_data;
size_t write_clen, enc_src_len;
int err;
if (ENC_ZIP_ENABLED(comp_enc_flags)){
write_cdata = kmalloc(get_compress_fsize(PAGE_SIZE), GFP_KERNEL);
if (!write_cdata) {
err = -ENOMEM;
goto zip_only;
}
}
else if(!(comp_enc_flags & ENC))
write_cdata = write_data;
else{
rd_enc_data = read_data;
enc_src_len = read_len;
goto enc_only;
}
err = do_compress(read_data, read_len, write_cdata, &write_clen);
if (err < 0) {
goto out_enc_zip;
}
if (!(comp_enc_flags & ENC)) {
*write_len2 = write_clen;
goto zip_only;
}
rd_enc_data = write_cdata;
enc_src_len = write_clen;
enc_only:
err = do_skcipher_encrypt(rd_enc_data, enc_src_len, write_data, write_len2);
if (err < 0) {
}
out_enc_zip:
if (ENC_ZIP_ENABLED(comp_enc_flags))
kfree(write_cdata);
zip_only:
return err;
}
Compiler try it's best to produce warning, as the message say "maybe", the compiler don't know that ENC_ZIP_ENABLED(comp_enc_flags) will be false at the label out_enc_zip. Your code don't use an uninitialized value.
That say, I strongly disagree about your use case of goto, your code is unreadable, I take a lot of time just to understand where the code was going.
Your code could be simplified a lot, I'm not sure at 100% that this code have the same behavior as I said your code is hard to read:
#define ENC (1UL << 1)
#define ZIP (1UL << 2)
int handle_comp_enc(unsigned long comp_enc_flags, unsigned char *read_data,
size_t read_len, unsigned char *write_data, size_t *write_len2) {
if ((comp_enc_flags & (ENC | ZIP)) == (ENC | ZIP)) {
unsigned char *tmp = kmalloc(get_compress_fsize(PAGE_SIZE), GFP_KERNEL);
if (!tmp) {
return -ENOMEM;
}
size_t size;
int err = do_compress(read_data, read_len, tmp, &size);
if (!(err < 0)) {
err = do_skcipher_encrypt(tmp, size, write_data, write_len2);
}
kfree(tmp);
return err;
}
else if (!(comp_enc_flags & ENC)) {
return do_compress(read_data, read_len, write_data, write_len2);
}
else {
return do_skcipher_encrypt(read_data, read_len, write_data, write_len2);
}
}
Yeah it looks like a false positive. In your if-else if-else, you only initialize the variable inside the if and else if statements. Apparently you got the tool confused with goto or some such.
But that's not really important, as the origin of the problems is the function design. You don't default initialize variables and you have a tight coupling between memory allocation and the actual algorithm. The use of goto here is ok but it reduces readability somewhat.
I would split this in two functions, where you leave memory handling and error handling to an outer function. Something along the lines of this pseudo code would be much more readable:
int wrapper_function ( ... )
{
unsigned char *write_cdata = NULL;
int err = initialize_me_to_something.
if(ENC_ZIP_ENABLED(comp_enc_flags))
{
write_cdata = kmalloc (...
if(write_cdata == NULL)
{
return -ENOMEM;
}
}
else
{
if(!(comp_enc_flags & ENC)
{
write_cdata = write_data;
...
}
else
{ // some special case
err = do_skcipher_encrypt(...
return err;
}
}
err = do_the_actual_job(write_cdata, otherparameters);
if (err < 0)
{
cleanup();
}
return err;
}
goto is not necessarily evil, but neither are multiple return statements. They are both frowned upon with more or less rational arguments provided. However, multiple return statements tend to improve readability quite a bit over the "on error goto" pattern. Most importantly, they tend to naturally give a better program design with multiple small functions instead of a single big one.
As a side effect, you get rid of some extra branching instructions, which might give a slight performance improvement.
I have a function which does some initialization and calls other functions, each of which returns an error code. I want to be able to return from this function after the first detected error like this:
int error_code = FirstFunction();
if (error_code != 0) {
return error_code;
}
error_code = SecondFunction();
if (error_code != 0) {
return error_code;
}
// etc...
However, not only does this look rather cumbersome, it also has multiple return statements, and for compliance reasons at my company this is not allowed.
How can I rearrange this so that there is only one return statement, but still stop after the first error code? The only way I can think of is to do nested if statements:
int error_code = FirstFunction();
if (error_code == 0) {
error_code = SecondFunction();
if (error_code == 0) {
error_code = ThirdFunction();
// etc...
}
}
return error_code;
But this could get unreasonable pretty fast. Is there another way to do this?
EDIT: In my program, return code of 0 means success (OK) and non-zero means failure/error (NOT OK)
You don't have to nest all the function calls, the code below do the job as well and should comply with your code writing rules:
error_code = FirstFunction();
if (error_code == 0) {
error_code = SecondFunction();
}
if (error_code == 0) {
error_code = ThirdFunction();
}
// etc...
return error_code;
Here is another lean method that can return different error codes depending on which function fails:
int func(void)
{
int code;
int error_code = (code = FirstFunction()) ? code :
(code = SecondFunction()) ? code :
(code = ThirdFunction()) ? code : 0;
/* ... */
return error_code;
}
Lean and clean (like this one, but avoiding the disliked gotos):
int foo(void)
{
int error_code;
do {
if (0 != (error_code = FirstFunction()))
{
break;
}
if (0 != (error_code = SecondFunction()))
{
break;
}
...
} while (0);
return error_code;
}
This, BTW, follows the more common pattern: 0 is OK, everything else isn't. Adjust as needed)
You could even obfuscate this using a macro:
#define RUN_AND_BREAK_ON_ERROR(rc, f, ...) \
if (0 != (rc = f(__VA_ARGS__))) \
{ \
break; \
}
int foo(void)
{
int error_code;
do {
RUN_AND_BREAK_ON_ERROR(error_code, FirstFunction, <args go here>);
RUN_AND_BREAK_ON_ERROR(error_code, SecondFunction, <args go here>);
...
} while (0);
return error_code;
}
if( (error_code = FirstFunction()) || (error_code = SecondFunction()) || ... ){
return error_code ;
}
return error_code; //denoting no error.
This would return only the first function which returns nonzero. The idea is that for if statement the first function that returns nonzero would short-circuit the whole evaluation and returns the error_code from the function which returned non-zero error_code. Also another thing is value of an assignment statement is the value assigned. That's why this works.
A more easier way would be to sequential if-else
if( error_code = FirstFunction() ) {}
else if( error_code = SecondFunction() ) {}
...
return error_code;
If all these functions take the same type of parameters and have the same return type, you could put them in a function array and iterate over it. When an error is found, it simply breaks out of the loop and returns.
int (*function_array[max_array])();
/*Fill the array with the functions you need*/
for(i=0;i<max_array;i++){
if((error_code=function_array[i]())!=OK){
break;
}
}
return error_code;
(OK is whatever the success return value is for these functions)
Well, there's the one used e.g. in the Linux kernel:
int somefunc(whatever)
{
if (do_something()) {
ret = -EINVAL;
goto err;
}
if (do_something_else()) {
ret = -EPERM;
goto err;
}
/* ... */
ret = 0;
err:
some_mandatory_cleanup();
return ret;
}
But I suspect that's going to be even less well received. (Before you scream, the whole point of that is the mandatory cleanup in the end. The goto arranges it to be executed always, but still puts it out of way.)
Really, I think the code in your first snippet is fine, and the issue is with your guidelines. Even if we only write return error_code; in one place, it's not enough to guarantee that the error code saved in variable is always correct, or that the function completes all cleanup that might be required. (Consider something that allocates memory, and has to release it in any case.)
I apologize for the naive question, Iam new to Net-SNMP. I have tried using this simple SNMP demo app given in Net-SNMP website.
This code performs a SNMP-GET and manipulates the response to check if the value returned is a ASN_OCTET_STRING, and if yes, access the string using vars->val.string and assigned to a character pointer sp.
But Iam unable to figure out how to access this value if the type is anything other than ASN_OCTET_STRING. For example how do I take this value and, say, assign it to a variable if it is of type 'ASN_INTEGER' or 'ASN_OBJECT_ID'.
#include <net-snmp/net-snmp-config.h>
#include <net-snmp/net-snmp-includes.h>
#include <string.h>
#define DEMO_USE_SNMP_VERSION_3
#ifdef DEMO_USE_SNMP_VERSION_3
const char *our_v3_passphrase = "MD5Password";
#endif
int main(int argc, char ** argv)
{
netsnmp_session session, *ss;
netsnmp_pdu *pdu;
netsnmp_pdu *response;
oid anOID[MAX_OID_LEN];
size_t anOID_len;
netsnmp_variable_list *vars;
int status;
int count=1;
init_snmp("snmpdemoapp");
snmp_sess_init( &session );
session.peername = strdup("localhost:161");
#ifdef DEMO_USE_SNMP_VERSION_3
session.version=SNMP_VERSION_3;
session.securityName = strdup("user2");
session.securityNameLen = strlen(session.securityName);
session.securityLevel = SNMP_SEC_LEVEL_AUTHNOPRIV;
session.securityAuthProto = usmHMACMD5AuthProtocol;
session.securityAuthProtoLen = sizeof(usmHMACMD5AuthProtocol)/sizeof(oid);
session.securityAuthKeyLen = USM_AUTH_KU_LEN;
if (generate_Ku(session.securityAuthProto,
session.securityAuthProtoLen,
(u_char *) our_v3_passphrase, strlen(our_v3_passphrase),
session.securityAuthKey,
&session.securityAuthKeyLen) != SNMPERR_SUCCESS) {
snmp_perror(argv[0]);
snmp_log(LOG_ERR,
"Error generating Ku from authentication pass phrase. \n");
exit(1);
}
#else /* we'll use the insecure (but simplier) SNMPv1 */
session.version = SNMP_VERSION_1;
session.community = "demopublic";
session.community_len = strlen(session.community);
#endif /* SNMPv1 */
SOCK_STARTUP;
ss = snmp_open(&session);
if (!ss) {
snmp_sess_perror("ack", &session);
SOCK_CLEANUP;
exit(1);
}
pdu = snmp_pdu_create(SNMP_MSG_GET);
anOID_len = MAX_OID_LEN;
if (!snmp_parse_oid("ip.21.1.8.xx.xx.xx.xx", anOID, &anOID_len)) {
snmp_perror("ip.21.1.8.xx.xx.xx.xx");
SOCK_CLEANUP;
exit(1);
}
snmp_add_null_var(pdu, anOID, anOID_len);
status = snmp_synch_response(ss, pdu, &response);
if (status == STAT_SUCCESS && response->errstat == SNMP_ERR_NOERROR) {
for(vars = response->variables; vars; vars = vars->next_variable)
print_variable(vars->name, vars->name_length, vars);
/* manipuate the information ourselves */
for(vars = response->variables; vars; vars = vars->next_variable) {
if (vars->type == ASN_OCTET_STR) {
char *sp = (char *)malloc(1 + vars->val_len);
memcpy(sp, vars->val.string, vars->val_len);
sp[vars->val_len] = '\0';
printf("value #%d is a string: %s\n", count++, sp); //Here sp now has the string - But this doesnt work when the string is for eg."HOST-RESOURCES-MIB::hrSWInstalledDate.1953 = STRING: 0-1-1,0:0:0.0"
free(sp);
}
else if(vars->type == ASN_INTEGER) {
printf("value is an Integer\n");
int ObjVal;
// How do I get the Integer value and assign it to 'ObjVal'
}
else if(vars->type == ASN_OBJECT_ID) {
printf("value is an OID\n");
// How do I get the OID and assign it to some variable
}
else if(vars->type == ASN_TIMETICKS) {
printf("value is in Timeticks\n");
// How do I get the Timeticks and assign it to some variable for further processing
}
}
} else {
if (status == STAT_SUCCESS)
fprintf(stderr, "Error in packet\nReason: %s\n",
snmp_errstring(response->errstat));
else if (status == STAT_TIMEOUT)
fprintf(stderr, "Timeout: No response from %s.\n",
session.peername);
else
snmp_sess_perror("snmpdemoapp", ss);
}
if (response)
snmp_free_pdu(response);
snmp_close(ss);
SOCK_CLEANUP;
return (0);
}
Tried vars->val.integer or vars->val.object_id, but that doesnot contain the value. What am I missing here?
My another question is, even when it is of type ASN_OCTET_STRING, when the GET reply is something like this,
HOST-RESOURCES-MIB::hrSWInstalledDate.1953 = STRING: 0-1-1,0:0:0.0
then vars->val.string doesnt have "0-1-1,0:0:0.0" as string.
Basically my question is How does the value get stored in the response structure from which I can retrieve the values?
Thanks in Advance!!
P.S: Makefile link from Net-SNMP website.
Edit1:
For Integers, i can read using *vars->val->string as pointed out by immibis. Any Ideas about how to access other datatypes?
As you can see in /usr/include/net-snmp/types.h file or similar on your system, net-snmp vars->val has the following union type:
typedef union {
long *integer;
u_char *string;
oid *objid;
u_char *bitstring;
struct counter64 *counter64;
#ifdef NETSNMP_WITH_OPAQUE_SPECIAL_TYPES
float *floatVal;
double *doubleVal;
/*
* t_union *unionVal;
*/
#endif /* NETSNMP_WITH_OPAQUE_SPECIAL_TYPES */
} netsnmp_vardata;
also *vars has val_len field, where the length of data stored.
So you can access integer as *vars->val.integer, string as pointer to u_char vars->val.string with vars->val_len chars, oid as pointer to oid vars->val.objid with vars->val_len/sizeof(oid) oid elements and so on.
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.
I'm trying to call execv after manually saerching for the program to execute.
In my case,
c is a struct which has args as an array of strings having the arguments passed while receiving input. nargs is the number of arguments.
c->args[0] would contain "ls","cat" etc.
I tried printing the value of the args[0], fullPath etc. in my child process. They all show values like "/bin/ls","/bin/cat" etc. But when I call execv, it returns -1 with an errno of 2, which I understand is the error for "No such file or directory". But I'm sure the file is there because thats what my PathResolver is returning after checking all permissions.
Can anyone point where I might have made a mistake.
//The part happening inside child
char *fullPath = PathResolver(c->args[0],1,&permission);
printf("FullPath: %s -- Permission: %d\n",fullPath,permission);
if(permission==0)
{
fprintf(stderr, "%s: Command not found\n",c->args[0]);
}
else if(permission==-1)
{
fprintf(stderr, "%s: Permission denied\n",c->args[0]);
}
else
{
char* args[c->nargs+1];
int m=0;
for(m=0;m<c->nargs;m++)
{
strcpy(args[m],c->args[m]);
}
args[c->nargs] = NULL;
printf("%d\n",execv(args[0], args));
printf("errno: %d\n",errno);
}
PathResolver function
char* PathResolver(char *command, int ResolverMode, int *Permission)
{
*Permission = 0;
char *returnString;
returnString = malloc((sizeof(char)));
char *strPath = getenv("PATH");
char *del = ":";
char *strToken = strtok(strPath,del);
FILE *f;
while(strToken)
{
char filePath[100];
sprintf(filePath,"%s/%s",strToken,command);
if(access(filePath,F_OK)>=0)
{
if(access(filePath,X_OK)>=0)
{
*Permission = 1;
sprintf(returnString,"%s%s ",returnString,filePath);
if(ResolverMode == 1)
break;
}
else
{
*Permission = -1;
}
}
strToken = strtok(NULL,del);
}
sprintf(returnString,"%s\b",returnString);
return returnString;
}
strcpy(args[m],c->args[m]); is undefined behaviour, because args[m] is not a pointer to valid memory.
The following might be simpler:
char * args[c->nargs + 1];
for (size_t m = 0; m != c->nargs; ++m)
{
args[m] = c->args[m];
}
args[c->nargs] = NULL;
There's no need to copy the strings.
(This may not be your actual problem, but it certainly prevents your program from being correct.)
execv() expects the program name to be prefixed by a full path as 1st parameter.
To have PATH searched instead of providing a path use execvp().
Update:
Also this line
returnString = malloc((sizeof(char)));
does only allocate 1 byte to returnString, which is way to few for how you use returnString.