I need to extract a substring from a string with different length. I would like to avoid using malloc.
Is this safe?
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main()
{
const char *PATTERN1 = "<Abcd.";
const char *PATTERN2 = ">";
const char *PATTERN3 = "<Fghi.";
char *begin, *end;
int len;
char result[50];
// lenght of toFind could be different i.e. "<Abcd.toGet>" or "<Abcd.toGettoGettoGet>" always less than 50
char *toFind[50] = {"<Abcd.toGettoGet>","<Abcd.toGettoGetoGet>","<Abcd.toGet>"};
int element = 3;
int i = 0;
for (i = 0; i < element ; i++) {
begin = strstr(toFind[i], PATTERN1);
printf("Begin: %s \n", begin);
if (begin == NULL) {
perror("Null begin\n");
}
begin += strlen(PATTERN1);
printf("Begin2: %s \n", begin);
end = strstr(begin, PATTERN2);
printf("End: %s \n", end);
if (end == NULL) {
perror("Null end\n");
}
len = end - begin;
printf("Len: %d \n", len);
strncpy(result, begin, len);
result[len] = '\0';
printf("Result = %s\n",result);
sleep(5);
}
return 0;
}
I'm wondering if this could be a correct and safe way to do it in order to avoid segmentation fault, or memory corruption/leak. Especially how *begin and *end it is initialized.
There are a few issues that you need to fix.
begin
or end
is NULL. You should add an else
part where you place the code that follows. Example:
if (begin == NULL) {
perror("Null begin\n");
} else {
begin += strlen(PATTERN1);
...
...
if (end == NULL) {
perror("Null end\n");
} else {
len = end - begin;
...
...
}
}
result
out of bounds. The result
array is fixed-size but len
can get any size. So using strncpy(result, begin, len);
will not protect you from out of bounds write. Add a check before using strncpy
strstr
returns NULL.ie
begin = strstr(toFind[i], PATTERN1);
printf("Begin: %s \n", begin); // Check for NULL **before** printing
No, it's terrible.
You use the result of strstr
before checking for NULL. This is a bug.
You don't check that len < sizeof(result)
, so the strncpy
is dangerous. This is a bug.
Using strncpy_s
would be safer if it were both available and well-implemented:
errno_t error = strncpy_s(result, sizeof(result), begin, len);
Apparently it isn't, so you need to correctly calculate the actual size yourself:
size_t copylen = min(sizeof(result)-1, len); strncpy(result, begin, copylen); result[copylen] = '\\0';
(observe how easy it is to get off-by-one errors with this sort of code, and don't just take my word for it: check and test it yourself).
If you want to wrap this into a function, you can't use a local array variable and return it.
The only easy way to fetch a substring with no allocation is to actually return the (pointer,length) or (original pointer,offset,length) tuples.
Otherwise, you need the caller to pass in a result array (and the correct size!), and this just pushes the allocation elsewhere.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.