C Curl 400 Bad Request keyword "on" - c

I wrote a C Program that calls a webservice with cURL. I started my test by hardcoding the address of the webservice with parameters like this :
http://....php?type=adresse&texte=XYZ
It worked fine so I've tried to concatenate a variable for field texte has shown below but it failed and returned me 400 Bad Request.
We checked the content of the request and there is a keyword "on" in front of the webservice address and I don't know where that come from.
on http://....php?type=adresse&texte=xyz&indDebut=0&indFin=1&epsg=900913&format=json"
char* mystrcat( char* dest, char* src )
{
while (*dest) dest++;
while (*dest++ = *src++);
return --dest;
}
recherche = "G0A3B0";
pcbak_adresse(recherche);
const char * pcbak_adresse(const char *details)
{
...
char * lien;
const char * fin_lien;
lien = "http://....php?type=adresse&texte=";
fin_lien = "&indDebut=0&indFin=1&epsg=900913&format=json";
/*Concatenation function*/
mystrcat(details, fin_lien);
mystrcat(lien, details);
/* Set CURL parameters */
curl_easy_setopt(curlHandler, CURLOPT_URL, lien);
curl_easy_setopt(curlHandler, CURLOPT_CUSTOMREQUEST, "GET");
curl_easy_setopt(curlHandler, CURLOPT_WRITEFUNCTION, callback_func);
curl_easy_setopt(curlHandler, CURLOPT_WRITEDATA, &str);
res = curl_easy_perform(curlHandler);
/* Check for errors */
if (res != CURLE_OK)
return curl_easy_strerror(res);
...
}
Thanks for your help!

No matter what mystrcat() is,
mystrcat(lien, details);
is wrong.
If it creates a new string composed by the two inputs, it's not being captured anywhere.
If it tries to write to lien it's undefined behavior. Because you cannot modify string literals which is what lien is.
The same reasoning probably applies to details, but you didn't post details declaration and/or definition.
Do not use anything like strcat() except if you want to do it only once.
To concatenate strings use something like a structure where you store the length of the current string, the size of the target array, and of course the target array. You can then resize the target when you need to, you don't need to find the end of the target string every time (which is what strcat() will do), you also have the advantage of controlling how you append to the string with a lot of detail.
To achieve what you want, you can do this
char lien[256];
int length;
length = snprintf(
lien,
sizeof(lien),
"http://....php?type=adresse&texte=%s&indDebut=0&indFin=1&epsg=900913&format=json",
details
);
if ((length >= sizeof(lien)) || (length == -1))
return error_occurred_here();
Also, returning a static string (which probably is what curl_easy_strerror() returns), and a tentatively dynamic one from the same function is bad design, because,
You can't tell whether it's an error or the JSON returned from the link.
You will need some method to determine whether it's a static string or the one generated in the function in order to free() it.

Related

How could I get directory name from the full path without using dirname()?

dirname() is really terrible, because it modifies the argument so that it need another ugly copy of the original string. So no dirname(), please.
Is there any function like that but which is able to use safely?
EDIT: To fix the horrible workaround when I was stupid (two years ago);
std::string_view getDirName(std::string_view filePath) {
return filePath.substr(0, filePath.rfind('/'));
}
Standard C99 or C11 do not know about directories, which is a notion provided by some operating system API (or some external library above it).
On Linux, dirname(3) man page shows examples calling strdup(3):
char *dirc, *basec, *bname, *dname;
char *path = "/etc/passwd";
dirc = strdup(path);
basec = strdup(path);
dname = dirname(dirc);
bname = basename(basec);
printf("dirname=%s, basename=%s\n", dname, bname);
(of course you should free both dirc and basec, and the code above don't check for failure of strdup)
You might also want the canonical directory of a path, using realpath(3). For example, you would code:
char* filepath = something();
char* canpath = realpath(filepath, NULL);
if (!canpath) { perror("realpath"); exit(EXIT_FAILURE); };
// so canpath is malloc-ed
char *candir = dirname(canpath); // would modify the string in canpath
/// use candir here, e.g.
printf("canonical directory for %s is %s\n", filepath, candir);
free (canpath);
BTW, glib offers g_path_get_dirname (whose result should be freed).
The freebsd man page of dirname(3) says that The dirname() function returns a pointer to internal storage space allocated on the first call that will be overwritten by subsequent calls. so check your documentation. Anyway, you can get a safe call if your implementation modifies directly the input string with:
char *aux = dirname(strdup(the_path));
...
free(aux);

Bus Error on void function return

I'm learning to use libcurl in C. To start, I'm using a randomized list of accession names to search for protein sequence files that may be found hosted here. These follow a set format where the first line is a variable length (but which contains no information I'm trying to query) then a series of capitalized letters with a new line every sixty (60) characters (what I want to pull down, but reformat to eighty (80) characters per line).
I have the call itself in a single function:
//finds and saves the fastas for each protein (assuming on exists)
void pullFasta (proteinEntry *entry, char matchType, FILE *outFile) {
//Local variables
URL_FILE *handle;
char buffer[2] = "", url[32] = "http://www.uniprot.org/uniprot/", sequence[2] = "";
//Build full URL
/*printf ("u:%s\nt:%s\n", url, entry->title); /*This line was used for debugging.*/
strcat (url, entry->title);
strcat (url, ".fasta");
//Open URL
/*printf ("u:%s\n", url); /*This line was used for debugging.*/
handle = url_fopen (url, "r");
//If there is data there
if (handle != NULL) {
//Skip the first line as it's got useless info
do {
url_fread(buffer, 1, 1, handle);
} while (buffer[0] != '\n');
//Grab the fasta data, skipping newline characters
while (!url_feof (handle)) {
url_fread(buffer, 1, 1, handle);
if (buffer[0] != '\n') {
strcat (sequence, buffer);
}
}
//Print it
printFastaEntry (entry->title, sequence, matchType, outFile);
}
url_fclose (handle);
return;
}
With proteinEntry being defined as:
//Entry for fasta formatable data
typedef struct proteinEntry {
char title[7];
struct proteinEntry *next;
} proteinEntry;
And the url_fopen, url_fclose, url_feof, url_read, and URL_FILE code found here, they mimic the file functions for which they are named.
As you can see I've been doing some debugging with the URL generator (uniprot URLs follow the same format for different proteins), I got it working properly and can pull down the data from the site and save it to file in the proper format that I want. I set the read buffer to 1 because I wanted to get a program that was very simplistic but functional (if inelegant) before I start playing with things, so I would have a base to return to as I learned.
I've tested the url_<function> calls and they are giving no errors. So I added incremental printf calls after each line to identify exactly where the bus error is occurring and it is happening at return;.
My understanding of bus errors is that it's a memory access issue wherein I'm trying to get at memory that my program doesn't have control over. My confusion comes from the fact that this is happening at the return of a void function. There's nothing being read, written, or passed to trigger the memory error (as far as I understand it, at least).
Can anyone point me in the right direction to fix my mistake please?
EDIT: As #BLUEPIXY pointed out I had a potential url_fclose (NULL). As #deltheil pointed out I had sequence as a static array. This also made me notice I'm repeating my bad memory allocation for url, so I updated it and it now works. Thanks for your help!
If we look at e.g http://www.uniprot.org/uniprot/Q6GZX1.fasta and skip the first line (as you do) we have:
MNAKYDTDQGVGRMLFLGTIGLAVVVGGLMAYGYYYDGKTPSSGTSFHTASPSFSSRYRY
Which is a 60 characters string.
When you try to read this sequence with:
//Grab the fasta data, skipping newline characters
while (!url_feof (handle)) {
url_fread(buffer, 1, 1, handle);
if (buffer[0] != '\n') {
strcat (sequence, buffer);
}
}
The problem is sequence is not expandable and not large enough (it is a fixed length array of size 2).
So make sure to choose a large enough size to hold any sequence, or implement the ability to expand it on-the-fly.

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.

Why is it evbuffer_add_printf will only accept static variables and not "dynamic" ones?

So far I have gotten my libev code to successfully return a static sting that says "OMP OMP", however when I write a function that returns a "static" string it never seems to work. (Sidenote: the idea is to turn that same function into a dynamic response but just for agile testing purposes I need this to work first). My code for the libev read callback is as the following...
void p2pserver_network_buf_read_callback(struct bufferevent *incoming, void *arg){
//Define function local variables
struct evbuffer *evreturn;
char *req;
//Begin function local logic
req = evbuffer_readline(incoming->input);
if (req == NULL){
return;
}
char *response;
parse_json_command(req, response);
//response = "OMP OMP";
g_print("PARSED");
evreturn = evbuffer_new();
evbuffer_add_printf(evreturn, "%s", response);
bufferevent_write_buffer(incoming,evreturn);
evbuffer_free(evreturn);
free(req);
g_print("%s", response);
}
The parse_json_command function is as the following...
void parse_json_command(char json_command, char *response){
//Define Local Variables
g_print("PARSING");
response = "YOU KNOW";
//Print out the recieved message....
//g_message("%s", json_command);
/**
* TODO: check if the JSON is valid before parsing
* to prevent "Segmentation Defaults"
* and its good sanity checks.
**/
//Parse JSON incomming
/*json_object * jobj = json_tokener_parse(json_command);
enum json_type type;
json_object_object_foreach(jobj, key, val){
g_print("%s\n", key);
if(g_utf8_collate(key, "cmd") >= 0){
//Looks like the user has sent a "cmd" (command), lets analyze the "val" (value) of that command to see what the caller/client needs to be attending to...
//Is the client requesting an "Identity Update" (Pings server: if this is the first time ping, the server and client will exachange keys if the relationship exists the server just accepts the encrypted "ping" packet update)
type = json_object_get_type(val);
if(type == json_type_string){
char* cmd_value;
cmd_value = json_object_get_string(val);
//g_print("VALUE:%d\n", g_utf8_collate(cmd_value, "identupdate"));
if(g_utf8_collate(cmd_value, "identupdate") == 0){
//Call "Identity Update Response"
//char return_response = p2pserver_json_identupdate_response(json_command);
}
}
}
}
*/
return;
}
If you want to see the complete code (only a couple of pages big at the time of this writing) you can go to the source code at the following link: https://github.com/Xenland/P2PCrypt-Server
Thanks for your time and help!
c passes arguments by value, not by reference. You problem is here:
void parse_json_command(char json_command, char *response){
[...]
response = "YOU KNOW";
[...]
}
char *response;
parse_json_command(req, response);
response is a uninitialized pointer to a string. You are assigning a pointer to a static string to the response pointer in the function, but that does not modify response outside of the function, it just changes response within the function. There are different ways to fix this. Probably the easiest one for a quick fix would be to change the function's prototype to return a char * instead of void:
char * parse_json_command(char json_command){
char *response;
[...]
response = "YOU KNOW";
[...]
return response;
}
char *response;
response = parse_json_command(req);
Also, the json_command argument should probably be a char * or const char *, not just a single char, if you want to pass more than a single byte there.

How to get metadata from Libextractor into a struct

I want to use Libextractor to get keywords/metadata for files.
The basic example for it is -
struct EXTRACTOR_PluginList *plugins
= EXTRACTOR_plugin_add_defaults (EXTRACTOR_OPTION_DEFAULT_POLICY);
EXTRACTOR_extract (plugins, argv[1],
NULL, 0,
&EXTRACTOR_meta_data_print, stdout);
EXTRACTOR_plugin_remove_all (plugins);
However, this calls the function EXTRACTOR_meta_data_print which "prints" it to "stdout"
I'm looking at a way to get this information to another function - i.e. pass or store this in memory for further working. The documentation was not clear to me. Any help or experience regarding this?
I've tried to install libextractor and failed to get it working (it always returns a NULL plugin pointer upon call to EXTRACTOR_plugin_add_defaults()), so what I will write next is NOT TESTED:
from : http://www.gnu.org/software/libextractor/manual/libextractor.html#Extracting
Function Pointer: int
(*EXTRACTOR_MetaDataProcessor)(void *cls,
const char *plugin_name,
enum EXTRACTOR_MetaType type,
enum EXTRACTOR_MetaFormat format,
const char *data_mime_type,
const char *data,
size_t data_len)
and
Type of a function that libextractor calls for each meta data item found.
cls
closure (user-defined)
plugin_name
name of the plugin that produced this value;
special values can be used (i.e. '<zlib>' for
zlib being used in the main libextractor library
and yielding meta data);
type
libextractor-type describing the meta data;
format basic
format information about data
data_mime_type
mime-type of data (not of the original file);
can be NULL (if mime-type is not known);
data
actual meta-data found
data_len
number of bytes in data
Return 0 to continue extracting, 1 to abort.
So you would just have to write your own function called whatever you want, and have this declaration be like:
int whateveryouwant(void *cls,
const char *plugin_name,
enum EXTRACTOR_MetaType type,
enum EXTRACTOR_MetaFormat format,
const char *data_mime_type,
const char *data,
size_t data_len)
{
// Do your stuff here
if(stop)
return 1; // Stops
else
return 0; // Continues
}
and call it via:
EXTRACTOR_extract (plugins, argv[1],
NULL, 0,
&whateveryouwant,
NULL/* here be dragons */);
Like described in http://www.gnu.org/software/libextractor/manual/libextractor.html#Generalities "3.3 Introduction to the libextractor library"
[here be dragons]: That is a parameter left for the user's use (even if it's redundant to say so). As defined in the doc: "For each meta data item found, GNU libextractor will call the ‘proc’ function, passing ‘proc_cls’ as the first argument to ‘proc’."
Where "the proc function" being the function you added (whateveryouwant() here) and proc_cls being an arbitrary pointer (can be anything) for you to pass data to the function. Like a pointer to stdout in the example, in order to print to stdout. That being said, I suspect that the function writes to a FILE* and not inevitably to stdout; so if you open a file for writing, and pass its "file decriptor" as last EXTRACTOR_extract()'s parameter you would probably end with a file filled with the information you can currently read on your screen. That wouldn't be a proper way to access the information, but if you're looking into a quick and dirty way to test some behavior or some feature; that could do it, until you write a proper function.
Good luck with your code!

Resources