这个子字符串在C中安全吗



我需要从不同长度的字符串中提取一个子字符串。我想避免使用malloc。

这安全吗?

#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 beginn");
}

begin += strlen(PATTERN1);
printf("Begin2: %s n", begin);
end = strstr(begin, PATTERN2);
printf("End: %s n", end); 

if (end == NULL) {
perror("Null endn");
}
len = end - begin;
printf("Len: %d n", len); 
strncpy(result, begin, len);
result[len] = '';

printf("Result = %sn",result);

sleep(5);
}

return 0;
}

我想知道这是否是一种正确而安全的方法,以避免分段错误或内存损坏/泄漏。特别是如何初始化它的开始和结束。

您需要解决一些问题。

  1. 不要只在beginend为NULL时继续

您应该在放置以下代码的位置添加一个else部分。示例:

if (begin == NULL) {
perror("Null beginn");
} else {
begin += strlen(PATTERN1);
...
...
if (end == NULL) {
perror("Null endn");
} else {
len = end - begin;
...
...
}
}
  1. 超出范围写入result

result数组是固定大小的,但len可以获得任何大小。因此,使用strncpy(result, begin, len);不会保护您不受越界写入的影响。在使用strncpy之前添加检查

  1. 如果strstr返回NULL,则不要打印字符串

begin = strstr(toFind[i], PATTERN1);
printf("Begin: %s n", begin);   // Check for NULL **before** printing

不,太可怕了。

  1. 在检查NULL之前使用strstr的结果。这是一个bug。

  2. 你没有检查len < sizeof(result),所以strncpy是危险的。这是一个bug。

    如果strncpy_s既可用又实施良好,那么使用它会更安全:

    errno_t error = strncpy_s(result, sizeof(result), begin, len);
    

    显然不是,所以你需要自己正确计算实际大小:

    size_t copylen = min(sizeof(result)-1, len);
    strncpy(result, begin, copylen);
    result[copylen] = '';
    

    (请注意,使用这种代码可以很容易地避免一个错误,不要只相信我的话:自己检查和测试(。

如果你想把它包装成一个函数,你不能使用本地数组变量并返回它。

在没有分配的情况下提取子字符串的唯一简单方法是实际返回(指针,长度(或(原始指针,偏移量,长度(元组。

否则,您需要调用方传入一个结果数组(以及正确的大小!(,这只会将分配推到其他地方。

相关内容

  • 没有找到相关文章

最新更新