Coverity deflect: - String length miscalculation (BAD_ALLOC_STRLEN) - c

I have a coverity deflect to be fixed but I am not sure about it. I have a function (void my_function(a_type *my_variable)) with the following problematic line of code:
body = malloc(strlen(&((my_type*) *my_variable)->Param2.body[1]) +1);
where body is an unsigned char*.
The Coverity message:
String length miscalculation (BAD_ALLOC_STRLEN)
Using "strlen(((my_type *)*my_variable)->Param2.body + 1)"
instead of "strlen(((my_type *)*my_variable)->Param2.body) + 1"
as an argument to "malloc" might be an under-allocation.
Now, given the strlen function call, which looks like this:
strlen(&((my_type*) *my_variable)->Param2.body[1])
and this line is identical to:
strlen(&((my_type*) *my_variable)->Param2.body + 1)
So this should be changed according to the message, and the result would be:
body = malloc((strlen(&((my_type*) *my_variable)->Param2.body)+1) +1);
Why is bad such an argument for malloc? I do not see what is the actual problem here so I am unsure about this solution and/or its necessity.
Additional information is that, &((my_type*) *my_variable)->Param2.body[1] (simply &Param2.body[1]) will be copied into body using strcpy, like:
strcpy(body, &((my_type *) *my_variable)->Param2.body[1]);

No, ...body[1] and ...body + 1 are not identical. The first has a type that is the element type of the body array, the second has type ptr-to-element-type. Read your C book again :-)
Coverity tries to tell you that you make the same error as in
char foo[42];
/* write a string to foo */
bar = malloc (strlen(foo + 1)); /* which is strlen(&foo[1]) */
when the correct code is
bar = malloc (strlen(foo) + 1);

I think you misunderstood the paranthesis.
The + 1 in the coverity suggestion is outside the strlen(...)
I think coverity gets worried because you want to take strlen from index 1 instead of index 0. Coverity would expect index 0 as starting point - like:
body = malloc(strlen(&((my_type*) *my_variable)->Param2.body[0]) +1);
^
which is also
body = malloc(strlen(((my_type*) *my_variable)->Param2.body) +1);
^ ^
No & operator No [0]
as suggested by coverity

I have reached that conclusion #rici was correct. Considering the following simulation:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
typedef struct Param2{
char* body;
}Param2;
int main()
{
Param2 test;
test.body = "test_string\0";
printf("%s, size: %d + 1 terminating null\n\n",test.body, strlen(test.body));
printf("original: %d \n", (strlen(&test.body[1]) + 1));
printf("what coverity thinks: %d \n", strlen(test.body + 1));
printf("what coverity suggests: %d \n", (strlen(test.body) + 1));
printf("a more transparent way: %d \n\n", (strlen(test.body + 1) + 1));
return 1;
}
This is the output:
There are three cases (4th is the same as 1st). The allocated memory can be seen on the image above for all cases. Now, if we want to copy the source string from the 2. byte (&body[1]), that would mean 10 bytes of data in the example. And according to the strcpy documentation:
To avoid overflows, the size of the array pointed by destination shall
be long enough to contain the same C string as source (including the
terminating null character), and should not overlap in memory with
source.
We need one more for the null termination giving us 11 bytes to be allocated. Coverity believes that we are allocating 10 bytes, and suggest to allocate 12.
But as we can see, the original code allocates 11 bytes which is the exact number of bytes we need here, making the coverity deflect false positive.

Related

Access violation when writing location

So my code should work this way:
the function gets as input a char**(array of strings) and just char*(string), also int number.
then, I have to realloc the char** to the number, and add to the last pointer in him the string. Here is how I wrote that:
void addReason(char** stringsArr, char* string, int number)
{
stringsArr = (char**)realloc(type, sizeof(char) * number);
*(stringsArr + number - 1) = (char)malloc(sizeof(char) * strlen(string));
strcpy(*(stringsArr + number - 1), string); // the exception thorws here,
//talking about the *(stringsArr + number - 1) pointer
}
First:
stringsArr = (char**)realloc(type, sizeof(char) * number);
should be:
stringsArr = realloc(stringsArr, sizeof(char *) * number);
or even better:
stringsArr = realloc(stringsArr, sizeof(*stringsArr) * number);
Note the parameter to the sizeof operator, and don't cast the return from realloc or malloc.
Second:
*(stringsArr + number - 1) = (char)malloc(sizeof(char) * strlen(string));
should be:
stringsArr[number-1] = malloc(strlen(string) + 1);
sizeof(char) is 1 by definition, so you don't need to specify it. You need to add 1 for the terminating null. Array index notation is generally easier to follow than pointer notation.
Third, on the off-chance that reason actually is a valid identifier and not a copy-paste error:
strcpy(*(stringsArr + number - 1), reason);
should be:
strcpy(stringsArr[number - 1], string);
As additional points:
You should always be checking the return value of malloc and friends.
All identifiers starting with str and a lowercase letter are reserved for the standard library, so your stringsArr and string are technically illegal identifiers.
As noted in the comments, you don't return your new pointer, so you're leaking your new memory here, but since your code clearly doesn't compile anyway, maybe there's more code you're not showing us.

C strcpy crashes code

I have the following code, the code crashes whenever the strcpy function is called. When these lines are commented out the code does not crash. What is wrong?
char cities[80][17];
char char_distances[40][2];
int distances[40];
char cities_sorted[20][17];
while (!feof(Text)) {
fscanf(Text, "%[^\t]\t%[^\t]\t%[^\n]\n",
cities[i], cities[i + 1], char_distances[i]);
distances[i] = atoi(char_distances[i]);
printf("City_start: %s City_end: %s Distance: %d \n",
cities[i], cities[i + 1], distances[i]);
static char uniqueCities[21][17];
int uniqueCitiesCount;
for (int j = 0; j < 21; j++) {
printf("%s\n", uniqueCities[i]);
bool start_unique = !areEqual(cities[i], cities[j]);
bool end_unique = !areEqual(cities[i], cities[j + 1]);
if (start_unique) {
strcpy(uniqueCities[uniqueCitiesCount], cities[i]);
uniqueCitiesCount++;
}
if (end_unique) {
strcpy(uniqueCities[uniqueCitiesCount], cities[i + 1]);
strcpy(uniqueCities[uniqueCitiesCount], cities[i + 1]);
uniqueCitiesCount++;
}
}
i++;
}
Thanks
What's wrong?
Well many things:
you posted a code fragment: this is not enough information to get help diagnosing your problem. The code posted cannot be compiled and tested, does not even have definitions for all the symbols in the fragment: how is Text defined? how was it opened? is it guaranteed to be different from NULL?
i is not defined in the fragment, how is it defined? is it initialized?
while (!feof(Text)) is not a good way to test for end of input, you should instead compare the result of fscanf() with the expected number of conversions.
fscanf(Text, "%[^\t]\t%[^\t]\t%[^\n]\n", does not have enough information to avoid buffer overflows. The maximum number of characters to store into the arrays should be specified this way: fscanf(Text, "%16[^\t]\t%16[^\t]\t%1[^\n]\n",. Note however that if the input is not consistent with these limitations, conversions will fail and the rest of the input file will be read out of sync. You shoud read the lines into a line buffer and use sscanf() to parse the lines.
char char_distances[40][2]; defines an array of array that can only contain 1 character and a null terminator. The distances must all be expressed as a single digit in the input file. You should probably define the arrays with a larger size or convert the distance directly into the distances array with a %d conversion specifier.
int uniqueCitiesCount; defines a local variable that is not initialized. Using it in your loop invokes undefined behavior as you probably try to access beyond the end of the 2D array.
printf("%s\n", uniqueCities[i]); will print an empty string as no city has yet been copied to this array.
bool start_unique = !areEqual(cities[i], cities[j]); how are bool and areEqual() defined?
strcpy(uniqueCities[uniqueCitiesCount], cities[i + 1]); is duplicated. The index i + 1 is incorrect.
The logic in the loop is contorted and probably flawed. You should just compare the city name with all entries in the uniqueCities and only add it the this array after the loop if it has not been found.

strtol result mismatch while string conversion

After checking out this question I did not found required solution, so I've tried to use strtol in following manner:
in = (unsigned char *)malloc(16);
for(size_t i = 0; i < (size_t)strlen(argv[2]) / 2; i+=2 )
{
long tmp = 0;
tmp = strtol((const char *)argv[2] + i, &argv[2] + 2, 16);
memcpy(&in[i], &tmp, 1);
}
This code produced several intermediate values:
Can someone please explain me why entire in array gets filled by 0xFF(255) bytes and why tmp is not equal it's estimated value?
Tips about how to improve above code to fill in array with correct hex values also welcome.
Your code is erroneous for multiple counts and the casts hide the problems:
Casting the return value of malloc is not necessary in C and can potentially hide an unsafe conversion if you forget to include <stdlib.h>:
in = (unsigned char *)malloc(16);
Casting the return value of strlen to (size_t) is useless, even redundant as strlen is defined to return a size_t. Again you might have forgotten to include <string.h>...
for (size_t i = 0; i < (size_t)strlen(argv[2]) / 2; i += 2) {
long tmp = 0;
strtol takes a const pointer to char, which argv[2] + i will convert to implicitly. The cast (const char*) is useless. The second argument is the address of a char*. You pass the address of the fifth element of argv, in other terms &argv[4], most certainly not what you indent to do, although your loop's purpose is quite obscure...
tmp = strtol((const char *)argv[2] + i, &argv[2] + 2, 16);
Copying the long value in tmp with memcpy would require to copy sizeof(tmp) bytes. Copying the first byte only has an implementation defined effect, depending on the size of char and the endianness of the target system:
memcpy(&in[i], &tmp, 1);
}
You should post a complete compilable example that illustrates your problem, a code fragment is missing important context information, such as what header files are included, how variables are defined and what code is executed before the fragment.
As written, your code does not make much sense, trying to interpret its behavior is pointless.
Regarding the question in reference, your code does not even remotely provide a solution for converting a string of hexadecimal characters to an array of bytes.

printf() won't print string in c

I'm trying to print a char array after a for loop to see the output to make sure it's correct. However, it won't print the string. Why won't it print the string? Am I missing something? It prints the index println string but not the Tag bit won't print. What am I missing?
Here is my code
char *getTag(char *address){
char *binary, *resultsIndex, *resultsTag, *resultsOffset;
char* tags;
int i, j, t;
printf("Get Tag function\n");
binary = hexToBin(address);
printf("Binary : %s\n", binary);
printf("Tag : %i\n", TAG);
printf("Offset : %i\n", OFFSET);
/*Seperate index, tag and offset*/
i = 0;
resultsIndex = (char * )malloc(sizeof(char) * INDEX);
for(i = 0; i < INDEX; i++){
resultsIndex[i] = binary[i];
}
resultsTag = (char * )malloc(sizeof(char) * TAG);
//resultsTag = '\0';
for(t = INDEX; t < TAG + 1; t++){
resultsTag[t] = binary[t];
printf("binary[i] %c\n", binary[t]);
printf("resultsTag[i] %c\n", resultsTag[t]); //<----prints individual character
}
printf("Index bit: %s\n", resultsIndex);
printf("Tag Bit %s", resultsTag); //<-----Won't print the string
return resultsTag;
}
I tried googling the problem and have tried some of the methods. One to make resultsTag[t] = '\0'. I tried that and it won't print still. Is something wrong with my for loop that can cause that?
It prints the individual character inside the loop, so I can see that it is storing it but it won't print it outside the loop. Any advice that could be helpful?
You write toresultTag starting from an offset INDEX, but attempt to print it from the initialised start. If the start happens to contain zero, it will print nothing.
Moreover, the final print does not end in a newline and the output stream is not flushed so will not be displayed immediately on some systems.
If I understand correctly, you are trying to split a string at two defined points, right? It appears you have a string in binary which has the following format:
XXXXYYYYYYZZZ0
^ ^ ^ ^
| | | \String terminator
| | \Offset
| \Tag
\Index
The length of the individual parts is of course just an example because I don't see your constant values. But according to my example, you may have the variables defined like this (specifying the end of them in the string):
#define INDEX 4
#define TAG 10
#define OFFSET 13
Now what the first problem is why it immediately doesn't work for you: You are not constructing resultsTag correctly. But let's first take a look at resultsIndex.
resultsIndex kind of works, but it also not done correctly. I'll explain you why. You are doing this:
resultsIndex = (char * )malloc(sizeof(char) * INDEX);
for(i = 0; i < INDEX; i++){
resultsIndex[i] = binary[i];
}
What it does:
Allocate INDEX (4 in my example) characters for the result string.
Loop from 0 to INDEX (4) exclusively, i.e. INDEX - 1 (3) inclusively and copy the data.
So i will get the values 0..1..2..3 during the loop. This means it will copy all characters from positions 0-3 in binary to positions 0-3 in resultsIndex.
After this part, resultsIndex is defined with a size of 4 characters (if we keep to my example values above) and looks like this:
____ << defined size
XXXX
...which is the index part of the string you copied. However, one mistake here is already that there is no string terminator! It should look like this:
_____ << defined size
XXXX0
^
\string terminator
A string terminator is what tells to whatever/whoever is reading the string later that it ends here and they have to stop reading there, otherwise they would read beyond the end.
However, because nothing stands alone but is normally surrounded by other parts of the memory, I guess it happened to look like this:
____ << defined size
XXXX00000000000...
^ ^
| \you were lucky that those null bytes were around
\this part you actually allocated
But you shouldn't rely on that. It might as well have looked like this:
____ << defined size
XXXXgarbage...
...then it would have printed XXXXgarbage instead of just XXXX. Or:
____ << defined size
XXXX| << here the memory block actually ends
...then it would have crashed trying to print it.
So, to fix this, you would have to reserve one more byte and fill it with a zero value, which acts as string terminator:
resultsIndex = (char * )malloc(sizeof(char) * (INDEX + 1));
for(i = 0; i < INDEX; i++){
resultsIndex[i] = binary[i];
}
resultsIndex[INDEX] = 0; // string terminator
OK now back to resultsTag. In my example above (and it looks like you are doing it similarly), my constant TAG was defined as 10, which is basically the length of the part before the tag (the index: 4) and the tag itself (6) together. But the tag itself is only 6 characters (= TAG - INDEX).
At the moment, you are doing this (I removed some things for clarity):
resultsTag = (char * )malloc(sizeof(char) * TAG);
for(t = INDEX; t < TAG + 1; t++){
resultsTag[t] = binary[t];
printf("resultsTag[i] %c\n", resultsTag[t]);
}
What it does:
Allocate TAG (10 in my example) bytes for the result string.
Loop from INDEX (4 in my example) to TAG + 1 (11) exclusively, i.e. TAG inclusively (10), so actually one char after the end of the tag.
So, the variable t will get the values 4..5..6..7..8..9..10 during the loop.
Effectively, this copies the data from positions 4-10 in binary to positions 4-10 in resultsTag.
The last part is the reason why it doesn't print (but that's not the only problem in your code). After this loop, the memory starting at where resultsTag is located will look like this:
__________ << defined size
????YYYYYYZ
^ ^ ^
| | \this is actually written outside of the allocated block of memory
| \this are the 6 characters of the tag you copied
\you never wrote to this part, so nobody knows what is there
Following my assumption from earlier, that memory you are allocating using malloc is implicitely filled with zero bytes by the system (which, again, is nothing you should rely on), it is likely that it actually looks like this:
__________ << defined size
0000YYYYYYZ
^ ^ ^
| | \this is actually written outside of the allocated block of memory
| \this are the 6 characters of the tag you copied
\zero values - remember that they act as string terminator!
So what happens when you try to print resultsTag? The system will look at the memory and say: OK, let's print. What is the first character? ...Oh, a string terminator already? Well that was short! Nothing to print! Good night.
And so nothing gets printed because your string starts with a red flag saying "string ends here". :P
So this last part has three problems:
You are allocating the wrong amount of memory and start writing to the middle of it instead of from the beginning.
You write beyond the end of it (because of TAG + 1 in the loop).
You again don't terminate the string.
Let me fix it:
resultsTag = (char * )malloc(sizeof(char) * (TAG - INDEX + 1));
for(t = INDEX; t < TAG; t++){
resultsTag[t - INDEX] = binary[t];
printf("resultsTag[i] %c\n", resultsTag[t - INDEX]);
}
resultsTag[TAG] = 0; // string terminator
For sake of completeness, here is what it does:
Allocate memory for the length of the tag only (not index plus tag), plus 1 byte for the string terminator. In my example it would be 6+1=7 bytes.
Loop from INDEX (4 in my example) to TAG (10) exclusively, i.e. TAG - 1 inclusively (9), but we don't use the same index for source and destination of the copying:
The variable t will get the values 4..5..6..7..8..9 during the loop, but the destination index will start at 0, not 4 this time, and will go through 0..1..2..3..4..5.
Effectively, this copies the data from positions 4-9 in binary to positions 0-5 in resultsTag.
So, resultsTag will look like this:
_______ << defined size
YYYYYY0
It would probably be a bit less confusing if TAG weren't defined as "length of index plus length of tag" but just as the length of the tag, because then the calculations were simpler and more obvious, but I'll leave that as an exercise ;)
I can see several other issues with your code too:
1) You are leaking memory because resultsIndex is not freed (i.e. free(resultsIndex); resultsIndex = NULL;) after you finished using it. If you really want to get only the tag (as the function name getTag suggests), you wouldn't need the whole part with resultsIndex at all, though... I don't know what you do with the value of resultsTag after returning it, but you have to make sure that the caller frees it as well!
2) Actually, binary smells like another memory leak. How does hex2bin allocate the memory for the string it returns? If it's also just malloc and there is no magic memory management, you would need to use free(binary); at the end as well.
3) i = 0; is superflouous because you set it to zero two lines below this as well.
First of all you are accessing your resultTag malloc-ated array out of bounds due to condition: t < TAG + 1; You have to loop until TAG-1 to leave space for null terminator. Or malloc TAG+1 bytes.
Secondly you must add a null terminator to your string to make it a C-String.
resultsTag = malloc(sizeof(char) * TAG+1);
for(t = INDEX; t < TAG; t++)
{
resultsTag[t] = binary[t];
printf("binary[i] %c\n", binary[t]);
printf("resultsTag[i] %c\n", resultsTag[t]); //<----prints individual character
}
resultsTag[t] = '\0';
Same considerations for resultsIndex
resultsIndex = (char * )malloc(sizeof(char) * INDEX+1);
for(i = 0; i < INDEX; i++){
resultsIndex[i] = binary[i];
}
resultsIndex[i] = '\0';
As Clifford points out the loop start filling your string from INDEX, then you must print the string starting from that offset.
printf("Tag Bit %s\n", &resultsTag[INDEX]);
or change the assignment inside the loop:
resultsTag[t-INDEX] = binary[t];
Furthermore you have to be sure that all values pointed by binary are ASCII.
You need to flush stdout, or add a \n (stdout autoflush on new-line)
printf("Tag Bit %s\n", resultsTag); //<-----Won't print the string
fflush (stdout);

Reallocing a char*

I am trying to do a function that will store in a char array some information to print on it:
int offset = 0;
size_t size = 1;
char *data = NULL;
data = malloc(sizeof(char));
void create(t_var *var){
size_t sizeLine = sizeof(char)*(strlen(var->nombre)+2)+sizeof(int);
size = size + sizeLine;
realloc(data, size);
sprintf(data+offset,"%s=%d\n",var->name,var->value);
offset=strlen(data);
}
list_iterate(aList, (void *)create);
t_var is a struct that has two fields: name (char*) and value (int).
What's wrong with this code? When running it on Valgrind it complains about the realloc and sprintf.
Without knowing the specific valgrind errors, the standout one is:
realloc(data, size); should be data = realloc(data, size);
I'm sorry to say that, but almost EVERYTHING is wrong with your code.
First, incomplete code.
You say your t_var type has two members, name and value.
But your code refers to a nombre member. Did you forget to mention it or did you forget to rename it when publishing the code?
Second, misused sizeof.
You use a sizeof(int) expression. Are you aware what you actually do here?!
Apparently you try to calculate the length of printed int value. Alas, operator sizeof retrieves the information about a number of bytes the argument occupies in memory. So, for example, for 32-bits integer the result of sizeof(int) is 4 (32 bits fit in 4 bytes), but the maximum signed 32-bit integer value is power(2,31)-1, that is 2147483647 in decimal. TEN digits, not four.
You can use (int)(2.41 * sizeof(any_unsigned_int_type)+1) to determine a number of characters you may need to print the value of any_unsigned_int_type. Add one for a preceding minus in a case of signed integer types.
The magic constant 2.41 is a decimal logarithm of 256 (rounded up at the 3-rd decimal digi), thus it scales the length in bytes to a length in decimal digits.
If you prefer to avoid floating-point operations you may use another approximation 29/12=2.41666..., and compute (sizeof(any_unsigned_int_type)*29/12+1).
Third, sizeof(char).
You multiply the result of strlen by sizeof(char).
Not an error, actually, but completely useless, as sizeof(char) equals 1 by definition.
Fourth, realloc.
As others already explained, you must store the return value:
data = realloc(data, size);
Otherwise you risk you loose your re-allocated data AND you continue writing at the previous location, which may result in overwriting (so destroying) some other data on the heap.
Fifth, offset.
You use that value to determine the position to sprintf() at. However, after the print you substitute offset with a length of last printout instead of incrementing it. As a result consecutive sprintfs will overwrite previous output!
Do:
offset += strlen(data);
Sixth: strlen of sprintf.
You needn't call strlen here at all, as all functions of printf family return the number of characters printed. You can just use that:
int outputlen = sprintf(data+offset, "%s=%d\n", var->name, var->value);
offset += outputlen;
Seventh: realloc. Seriously.
This is quite costly function. It may need to do internal malloc for a new size of data, copy your data into a new place and free the old block. Why do you force it? What impact will it have on your program if it needs to print five thousand strings some day...?
It is also quite dangerous. Really. Suppose you need to print 5,000 strings but there is room for 2,000 only. You will get a NULL pointer from realloc(). All the data printed to the point are still at the current data pointer, but what will you do next?
How can you tell list_iterate to stop iterating...?
How can you inform the routine above the list_iterate that the string is incomplete...?
There is no good answer. Luckily you needn't solve the problem — you can just avoid making it!
Solution.
Traverse your list first and calculate the size of buffer you need. Then allocate the buffer — just once! — and go on with filling it. There is just one place where the allocation may fail and you can simply not go into the problem if that ever happens:
int totaloutputlength = 0;
char *outputbuffer = NULL;
char *currentposition = NULL;
void add_var_length(t_var *var){
const int numberlength = sizeof(var->value)*29/12 + 1;
totaloutputlength += strlen(var->name) + 2 + numberlength;
}
void calculate_all_vars_length(t_list *aList){
totaloutputlength = 0;
list_iterate(aList, (void *)add_var_length);
}
void sprint_var_value(t_var *var){
int outputlen = sprintf(currentposition, "%s=%d\n", var->name, var->value);
currentposition += outputlen; // advance the printing position
}
int sprint_all_vars(t_list *aList){
calculate_all_vars_length(aList);
outputbuffer = malloc(totaloutputlength + 1); // +1 for terminating NUL char
// did allocation succeed?
if(outputbuffer == NULL) { // NO
// possibly print some error message...
// possibly terminate the program...
// or just return -1 to inform a caller something went wrong
return -1;
}
else { // YES
// set the initial printing position
currentposition = outputbuffer;
// go print all variables into the buffer
list_iterate(aList, (void *)sprint_var_value);
// return a 'success' status
return 0;
}
}

Resources