2016-01-12 24 views
0

我的php_substr函数应该将kpart设置为a33c5b4b58b26d9f,但是它会将其设置为a33c5b4b58b26d9fÿÿ¯www。C函数substr,PHP扩展,strncpy错误长度

任何想法?

long ks; 
char *kpart1; 

ks = 16; 
php_substr("a33c5b4b58b26d9f78293df1c5d5a3bf", &kpart1, 0, ks); // a33c5b4b58b26d9fìÿ?꬯wÿÿÿÿ®w 

char *php_substr(char *str, char **ptr, long f, long l) 
{ 
    int str_len = strlen(str); 

    if (!l) { 
     l=0; 
    } 

    if (l!=0) { 
     if ((l < 0 && -l > str_len)) { 
      return FALSE; 
     } else if (l > str_len) { 
      l = str_len; 
     } 
    } else { 
     l = str_len; 
    } 

    if (f > str_len) { 
     return FALSE; 
    } else if (f < 0 && -f > str_len) { 
     f = 0; 
    } 

    if (l < 0 && (l + str_len - f) < 0) { 
     return FALSE; 
    } 

    if (f < 0) { 
     f = str_len + f; 
     if (f < 0) { 
      f = 0; 
     } 
    } 

    if (l < 0) { 
     l = (str_len - f) + l; 
     if (l < 0) { 
      l = 0; 
     } 
    } 

    if (f >= str_len) { 
     return FALSE; 
    } 

    if ((f + l) > str_len) { 
     l = str_len - f; 
    } 

    strncpy(*ptr,str+f,l); 
    return 0; 
} 

编辑为使用malloc并包含完整的工作代码!

我试过了Zend Engine emalloc然而,这似乎并没有工作

long ks; 
char *kpart1; 

ks = 16; 
kpart1 = php_substr("a33c5b4b58b26d9f78293df1c5d5a3bf", 0, ks); // a33c5b4b58b26d9f 

char *php_substr(char *str, long f, long l) 
{ 
    int str_len = strlen(str); 
    unsigned char *buffer; 

    if (l!=0) { 
     if ((l < 0 && -l > str_len)) { 
      return FALSE; 
     } else if (l > str_len) { 
      l = str_len; 
     } 
    } else { 
     l = str_len; 
    } 

    if (f > str_len) { 
     return FALSE; 
    } else if (f < 0 && -f > str_len) { 
     f = 0; 
    } 

    if (l < 0 && (l + str_len - f) < 0) { 
     return FALSE; 
    } 

    if (f < 0) { 
     f = str_len + f; 
     if (f < 0) { 
      f = 0; 
     } 
    } 

    if (l < 0) { 
     l = (str_len - f) + l; 
     if (l < 0) { 
      l = 0; 
     } 
    } 

    if (f >= str_len) { 
     return FALSE; 
    } 

    if ((f + l) > str_len) { 
     l = str_len - f; 
    } 

    buffer = (char*)malloc(l+1); 
    strncpy(buffer,str+f,l); 
    buffer[l]='\0'; 
    return buffer; 
} 
+3

您是否知道,如果超过可用长度,strncpy将不会正确地终止字符串?我不知道这是否是问题,但人们通常不知道'strncpy'。 – user694733

+1

'php_substr(key1,&kpart1,0,ks/2);''不能使用'&kpart1',因为'kpart1'不指向有效的内存缓冲区。所以当你在'strncpy(* ptr,str + f,l)'中使用它作为'dest'参数时,你会导致未定义的行为。 'kpart1'或者需要分配一个'malloc'调用的结果,或者需要一个静态分配的'char'数组。 – kaylum

+2

查看@ user694733的第一条评论。你的'缓冲区'没有被终止。而不是像'buffer = malloc(l + 1); n = strncpy(buffer,str + f,l);缓冲器[N] = 0;'。也就是说,明确地终止。 – kaylum

回答

0

修剪出来的参数

的全部测试编辑成编译/链接/运行文件后后

这是所得到的代码:

#include <stdio.h> 
#include <string.h> 
#define FALSE (0) 

char *php_substr(char *str, char **ptr, long f, long l) 
{ 
    strncpy(*ptr,str+f,(size_t)l); 
    return 0; 
} 

int main(void) 
{ 
    long int ks = 16; 
    char *kpart1; 

    php_substr("a33c5b4b58b26d9f78293df1c5d5a3bf", &kpart1, 0, ks); // a33c5b4b58b26d9fìÿ?꬯wÿÿÿÿ®w 
    printf("%s\n", kpart1); 
} 

请注意,字符指针:kpart1未初始化为指向任何特定位置。

(在这种情况下,它包含任何垃圾是在堆栈中。如果它是一个全局变量,它会contian NULL)

strncpy()呼叫试图复制的第一个16个字节中传递的不断地往往kpart1恰好指向。

strncpy()会导致未定义的行为,并可能导致seg故障事件。

我没有对传入变量fl的操作进行分析。

如您发现的那样,建议指针kpart1需要初始化为指向一些分配的内存,其中分配的内存的长度至少为l-f + 1。