Passing Variable Number of Arguments to an Entry in a Char* Array - c

I have been using the following link: https://www.embedded.com/design/programming-languages-and-tools/4215552/Seventeen-steps-to-safer-C-code to enhance the current error logging of a project I am working on.
My end goal is to generate an enum "error type". I would map these error types to a lookup table of char*'s which I could use to log a more detailed explanation of what the error is.
This way, I have all my error codes and corresponding error strings in a central location and can easily modify/lookup a message and errorcode without having to dig through the code.
As a PoC, my header file contains the following:
typedef enum {
ECODE_OK = 0, // OK
ECODE_SAMPLE_ERR = 1,
ECODE_LAST
} myEcodes;
char * ecodeMap[ECODE_LAST+1];
char * ecodeName(myEcodes err);
My implementation in C of the header is included below:
char * ecodeMap[ECODE_LAST+1] =
{
"No error to report",
"Example Error Code - Invalid Value",
"Last ecode place holder"
};
char * ecodeName(myEcodes err)
{
return (char *) eyescanEcodeMap[err];
}
My question is, say I have the following code snippet to log an error I encountered:
fprintf(fp, "%s", ecodeName(ECODE_SAMPLE_ERR));
What if I want ECODE_SAMPLE_ERR to actually contain a formatted string like
"Example Error Code - Invalid Values: %d %d", myVarInt1, myVarInt2
instead of just
"Example Error Code - Invalid Value"
What would be the best way to be able to format individual strings in my array of char* such that I can include the value of variables in particular entries?

If the main aim is to add print along with other variable values, let ERROR string be constant. You can just add additional values when you are writing to file fp.
fprintf(fp, "%s: %d %d", ecodeName(ECODE_SAMPLE_ERR), myVarInt1, myVarInt2);

Related

Parse JSON message manually in C

I need to parse manually, without external libraries, a JSON message coming from a server, in C language.
The message coming from server would be like:
{[CR+LF]
"Tmg": "R",[CR+LF]
"STP": 72[CR+LF]
}[CR+LF]
or
{[CR+LF]
"Tmg": "R",[CR+LF]
"STP": 150[CR+LF]
}[CR+LF]
I need the number after STP:. The number is different in each message structure, so I need to get that number from the JSON structure. I can't use external libraries because this code is in an embedded system and exernal code is not allowed.
I tried this following:
int main (){
const char response_message[35] = "{\r\n\"Tmg\":\"R\",\r\n\"STP\":72,\r\n}";
const char needle[8] = "P\":";
char *ret;
ret = strstr(response_message, needle);
printf("The number is: %s\n", ret);
return 0;
}
But obviously, I am getting this result:
The number is: P":72,
}
So I need to only get the number, how can I get this?
Thanks
You can use a hacked solution. Use strstr () to find "STP": then find the following , or } and extract the digits in between.
And that's a hack. Not guaranteed to work. For something that's guaranteed to work, you use a JSON parser.

How define array to fit negative indexes?

I am trying to write function which will return correct string when I will pass error in its argument. But it's not clear to me how to assign negative indexes to strings (corresponding to enum FILE_ERRORS_t), can you clarify?
typedef enum {
FOPEN_ERROR=-1,
FREAD_ERROR=-2,
FWRITE_ERROR=-3,
FSEEK_ERROR=-4,
FCLOSE_ERROR=-5
} FILE_ERRORS_t;
#define printErr (const char*[5]){"Cannot open file", "Cannot read file", "Cannot write file", "fseek fail", "fclose fail" }
You cannot make an array that takes negative indexes, but you can make a pointer to the middle of an array so that when you combine it with a negative index, you get a valid element of a "regular" C array. Here is how:
static char * real_errors[] = {
"fclose fail" // -5
, "fseek fail" // -4
, "Cannot write file" // -3
, "Cannot read file" // -2
, "Cannot open file" // -1
};
static char **errors = &real_errors[5]; // Point one element past the end
Now you can write this:
printf("%s\n", errors[FCLOSE_ERROR]);
and it would work, because it is equivalent to
printf("%s\n", real_errors[5+FCLOSE_ERROR]);
Demo.
Note: This is only well-defined if errors is pointing inside the array or one past the end. Otherwise, it would be undefined behavior.
Try taking the absolute value as described here and then subtracting one. Then -1 will become 0, -2 will become 1, etc. That should map as you want it to. So the function might looks something like this:
int errorCodeToIndex(FILE_ERRORS_t errorCode) {
return abs(errorCode) - 1
You may need to convert errorCode to an int and remember to #include <stdlib.h>.
You can use a negative index reversing the order of strings:
#include <stdio.h>
typedef enum {
FOPEN_ERROR=-1,
FREAD_ERROR=-2,
FWRITE_ERROR=-3,
FSEEK_ERROR=-4,
FCLOSE_ERROR=-5
} FILE_ERRORS_t;
#define sup ((const char *[]){"fclose fail", "fseek fail", "Cannot write file" ,"Cannot read file", "Cannot open file", ""} + 5)
int main(void)
{
puts(sup[FSEEK_ERROR]);
return 0;
}
Ouptut:
fseek fail
Just use a function-like macro and designated initializers
#define printErr(E) (const char*const[]){[-FOPEN_ERROR] = "Cannot open file", ... }[-E]
This makes the array as large as needed and ensures that each string is place at the correct position in it.

Expression: (L "String is not null terminated" & & 0)

I am fiddling around with mailslots and now I've run into a problem.
Whenever I try to run, I get the error message in the title, but I don't know how I should go about fixing it.
What I am trying to do is "fixing" the full path of the mailslot, but it seems to not like the strcat_s-part.
HANDLE mailslotCreate (char *name) {
char fullName[50] = "\\\\.\\mailslot\\";
strcat_s(fullName, strlen(fullName), name);
return CreateMailslot(fullName, 0, TIME_OUT, NULL);
}
Imgur link to error
EDIT: Changing the strlen to sizeof merely changed the error to "Buffer size too small" instead.
See documentation on strcat_s. It says that second parameter should be the size of destination buffer. As you pass strlen(fullName), there is no room for terminating \0.
Change it to be sizeof(fullName) and your error should disappear.

Tainted string in C

I'm running Coverity tool in my file operation function and getting the following error.
As you can see below, I'm using an snprintf() before passing this variable in question to the line number shown in the error message. I guess that some sanitization of the string has to be done as a part of that snprintf(). But still the warning is shown.
Error:TAINTED_STRING (TAINTED string "fn" was passed to a tainted string sink content.) [coverity]
char fn[100]; int id = 0;
char* id_str = getenv("ID");
if (id_str) {
id = atoi(id_str);
}
memset(fn, '\0', sizeof(fn));
snprintf(fn, 100, LOG_FILE, id);
if(fn[100-1] != '\0') {
fn[100-1] = '\0';
}
log_fp = fopen (fn, "a");
Any help would be highly appreciated.
Try the following:
char* id_str = getenv("ID");
if (id_str) {
id_str = strdup(id_str);
id = atoi(id_str);
free( id_str );
}
The fn string passed to fopen is tainted by an environment variable. Using strdup may act as "sanitizing".
Error:TAINTED_STRING is warning that (as far as Coverity can tell) some aspect of the behaviour is influenced by some external input and that the external input is not examined for 'safeness' before it influences execution.
In this particular example it would appear that Coverity is wrong because the value of LOG_FILE is "/log/test%d.log" and is used with an int in the snprintf, meaning that the content of char fn[100] is always well defined.
So a reasonable course of action would be to mark the error as a non-issue so that it is ignored on future runs.
Coverity wants to make sure you sanitize any string which is coming from outside of your program, be it getenv, argv, or from some file read.
You may have a function to sanitize the input(Tainted string) and have a comment provided by Coverty which tells Coverty that input string is sanitized and the SA warning will go away.
// coverity[ +tainted_string_sanitize_content : arg-0 ]
int sanitize_mystring(char* s)
{
// Do some string validation
if validated()
return SUCCESS;
else
return FAILED;
}
// coverity[ +tainted_string_sanitize_content : arg-0 ] is the line Coverty is looking
Hope this helps.

getting format not a string literal even if I add %s

I have looked around for answer on various forums, tried various things and still getting this error:
warning: format not a string literal and no format arguments [-Wformat-security]
The compiler point to the line in the function that has the error, here's how it looks:
int print_notes(int fd, int uid, char *searchstring) {
int note_length;
char byte=0, note_buffer[100];
note_length = find_user_note(fd, uid);
if(note_length == -1) // if end of file reached
return 0; // return 0
read(fd, note_buffer, note_length); // read note data
note_buffer[note_length] = 0; // terminate the string
if(search_note(note_buffer, searchstring)) // if searchstring found
scanf("%s", note_buffer) // Got this line from an answer in the forums
printf(note_buffer); // compiler points here
return 1;
}
If you want the full code i can post it here, but its kind of long :/ don't know if that will be ok.
Its giving warning for :
printf(note_buffer);
As you are getting string being formed at runtime and trying to print it.
Use :
printf("%s",note_buffer);

Resources