c-strncpy和代码的效率



我在编码过程中慢慢学习和进步,所以我希望有人能帮我快速了解一下这个函数,并告诉我我是否走在了正确的轨道上,我如何才能做得更好,或者我可能会在哪里失败。我是C世界的新手,所以请对我宽容一点——但要直率和诚实。

void test(char *username, char *password) {
    printf("Checking password for %s - pw: %sn",username,password);
    char *query1 = "SELECT password FROM logins WHERE email = '";
    char *query2 = "' LIMIT 1";
    char *querystring = malloc(strlen(query1) + strlen(username) + strlen(query2) * sizeof(char));
    strncpy(querystring,query1,strlen(query1));
    strncat(querystring,username,strlen(username));
    strncat(querystring,query2,strlen(query2));
    printf("Query string: %sn",querystring);
    mysql_query(mysql_con,querystring);
    MYSQL_RES *result = mysql_store_result(mysql_con);

    int num_fields = mysql_num_fields(result);
    int num_rows = mysql_num_rows(result);
    if (num_rows != 0) {
        MYSQL_ROW row;
        printf("Query returned %i results with %i fieldsn",num_rows,num_fields);
        row = mysql_fetch_row(result);
        printf("Password returned: %sn",row[0]);
        int comparison = strncmp(password, row[0], strlen(password));
        if (comparison == 0) {
            printf("Passwords match!n");
        } else {
            printf("Passwords do NOT match!n");
        }
    } else {
        printf("No such user... Password is invalid");
    }
    free(querystring);
}

目前,它正在发挥作用。。。输出:

Checking password for jhall@futuresouth.us - pw: 5f4dcc3b5aa765d61d8327deb882cf99
Query string: SELECT password FROM logins WHERE email = 'test@blah.com' LIMIT 1
Query returned 1 results with 1 fields
Password returned: 5f4dcc3b5aa765d61d8327deb882cf99
Passwords match!

调用:

test("test@blah.com","5f4dcc3b5aa765d61d8327deb882cf99");

我正在寻找关于我如何更好地处理字符串的意见,或者我如何处理字符串是否存在任何不可预见的问题。我对在C.中处理数据结构非常陌生

使用strncpy(target, source, strlen(source))可以保证target中的字符串不会以null结尾。如果malloc()可能返回零内存,那么它似乎可以工作,但一旦malloc()返回非零内存(以前分配的内存),事情就会出错。

strncat()的长度参数非常奇怪;它是在当前(null终止)数据之后目标字符串中剩余的空间量。除了没有以null结尾的字符串可供使用之外,您的使用并不能防止缓冲区溢出。

strncat() IMNSHO确实没有一个好的用例,strncpy()也很少有好的用例。如果你知道所有东西都有多大,你可以使用memmove()(或memcpy())。如果你不知道每件东西有多大,你就不知道在不截断的情况下进行复制是否安全。

您的malloc()调用也有点特殊:它没有为后面的null分配足够的空间,而且它只将三项中的一项乘以sizeof(char),这是不一致的,但在其他方面是无害的。很多时候,你会因为malloc()四舍五入而逃脱短期分配的惩罚,但如果你不逃脱惩罚,一切都会变得一团糟。像valgrind这样的工具会报告分配内存的滥用。

Jonathan的回答解释了该部分代码的问题。

要修复它,您可以使用snprintf代替:

size_t space_needed = strlen(query1) + strlen(username) + strlen(query2) + 1;
char *querystring = malloc(space_needed + 1);
if ( !query_string )
    exit(EXIT_FAILURE);
snprintf(query_string, space_needed, "%s%s%s", query1, username, query2);

然后,即使您计算的长度错误,至少您没有得到缓冲区溢出。

为了避免代码重复,这里有一个非标准函数asprintf,您可以通过它传递参数,并生成一个指向适当大小的malloc'd缓冲区的指针。当然,如果你不想依赖这个函数的存在,你可以编写自己版本的函数。

这里还有另一个严重的问题,即您的代码不能防止SQL注入(请参阅此处了解解释)。关于如何防止这种情况的适当讨论可能超出了这个问题的范围!

相关内容

  • 没有找到相关文章

最新更新