2013-02-27 75 views
-1

我已经经历了几个有关相同错误代码的类似问题,最关心的是传递无效指针地址。然而,这看起来不是这样,因为我的程序正确地处理任何地址通过回报。valgrind给出大小为1的无效读取

FORMAT_STRING:

static char *format_string(char *string) 
{ 
    int i; 

    if (string == NULL) { 
     return string; 
    } 
    string[0] = (char)toupper((int)string[0]); 

    111->for (i = 1; string[i] != '\0'; i++) { 
     if (!isalpha(string[i-1])) { 
      string[i] = (char)toupper((int)string[i]); 
     } else { 
      string[i] = (char)tolower((int)string[i]); 
     } 
     if (string[i] == '/' || string[i] == '\\') { 
     string[i] = ' '; 
     } 
    } 
    /* Remove End of string White Spaces */ 
    while (string[--i]==' '); string[++i]='\0'; 

    return string; 
} 

metadata_extract:

static int metadata_extract(const char *filename, struct kw_metadata *s) 
{ 
    char *memchar = NULL; 
    s->obj = NULL; 
    s->do_cleanup = &do_on_cleanup; 
    if (!is_of_type(filename)) {   
     return KW_ERROR; 
    } 

    TagLib_File* file = taglib_file_new(filename); 
    TagLib_Tag* tag = taglib_file_tag(file); 

    s->type = strdup("Audio"); 
    s->tagc = 4; 
    s->tagtype = (char **)malloc(4 * sizeof(char *)); 
    s->tagv = (char **)malloc(4 * sizeof(char *)); 

    memchar = strdup("title"); 
    s->tagtype[0] = memchar; 
    memchar = strdup("artist"); 
    s->tagtype[1] = memchar; 
    memchar = strdup("album"); 
    s->tagtype[2] = memchar; 
    memchar = strdup("genre"); 
    s->tagtype[3] = memchar; 

    153->memchar = strdup(taglib_tag_title(tag)); 
    memchar = format_string(memchar); 
    s->tagv[0] = memchar; 
    memchar = strdup(taglib_tag_artist(tag)); 
    memchar = format_string(memchar); 
    s->tagv[1] = memchar; 
    memchar = strdup(taglib_tag_album(tag)); 
    160->memchar = format_string(memchar); 
    s->tagv[2] = memchar; 
    memchar = strdup(taglib_tag_genre(tag)); 
    memchar = format_string(memchar); 
    s->tagv[3] = memchar; 

    s->obj = file; 
    s->do_init = &do_on_init; 
    s->do_cleanup = &do_on_cleanup; 

    taglib_tag_free_strings(); 
    taglib_file_free(file); 

    return KW_SUCCESS; 
} 

的valgrind:

==16769== Invalid read of size 1 
==16769== at 0x5317605: format_string (plugin_taglib.c:111) 
==16769== by 0x531781F: metadata_extract (plugin_taglib.c:160) 
==16769== by 0x405EB3: metadata_extract (metadata_extract.c:36) 
==16769== by 0x403351: add_metadata_file (dbbasic.c:221) 
==16769== by 0x4032D5: add_file (dbbasic.c:174) 
==16769== by 0x406485: import_semantics (import.c:97) 
==16769== by 0x406440: import_semantics (import.c:92) 
==16769== by 0x4065AC: import (import.c:127) 
==16769== by 0x401916: main (kwest_main.c:87) 
==16769== Address 0x6f4ce11 is 0 bytes after a block of size 1 alloc'd 
==16769== at 0x4C2B3F8: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so) 
==16769== by 0x57A6D71: strdup (strdup.c:43) 
==16769== by 0x531780F: metadata_extract (plugin_taglib.c:159) 
==16769== by 0x405EB3: metadata_extract (metadata_extract.c:36) 
==16769== by 0x403351: add_metadata_file (dbbasic.c:221) 
==16769== by 0x4032D5: add_file (dbbasic.c:174) 
==16769== by 0x406485: import_semantics (import.c:97) 
==16769== by 0x406440: import_semantics (import.c:92) 
==16769== by 0x4065AC: import (import.c:127) 
==16769== by 0x401916: main (kwest_main.c:87) 
+4

为什么'format_string'声明中的'const'?这是一个公然的谎言。 – aschepler 2013-02-27 18:51:52

+0

因为我必须通过函数地址,它期望它的格式:/ – kicker86 2013-02-27 18:56:32

回答

6

for (i = 0; string[i] != '\0'; i++) { 
    if (string[i-1]) { 

你正在阅读string[-1],通常为1

想必你的意思

for(i = 1; ... 

编辑后大小的无效读:

循环之前,你应该检查字符串在结束之前至少有一个字符,

if (string[0] == 0) return string; 

(最好在string[0] = (char)toupper((int)string[0]);之前完成)。消息

地址0x6f4ce11是0字节大小后1块alloc'd

告诉你,你strdup编辑字符串之一是空的(大小为1块是指只为0空间终端被分配)。

当你标记出尾部的空格,

while (string[--i]==' '); string[++i]='\0'; 

你不检查索引是否有效,如果整个字符串组成的空间,你至少读string[-1],你应该检查:

while(i-- > 0 && string[i] == ' '); 
string[++i] = 0; 
+0

改变,错误持续存在... – kicker86 2013-02-27 19:04:53

+0

已更新。不过,我在'format_string'中看不到更多的问题。 – 2013-02-27 19:18:31

+0

是的,我忽略了空串的可能性!非常感谢! – kicker86 2013-02-27 19:29:52

0

如果(NULL!= memchar)在实际使用变量之前尝试使用验证;否则strdup和功能都会带来不可预知的结果。