安全使用libcurl的正确姿势

来源:互联网 发布:霍尼韦尔2316简易编程 编辑:程序博客网 时间:2024/05/16 15:32

安全使用libcurl的正确姿势


在我们的项目中,数次遇到 libcurl 导致的应用程序崩溃问题,这里总结了一下使用 libcurl 的正确姿势。

 1: #include <curl/curl.h> 2: #include <stdint.h> 3: #include <string.h> 4:  5:  6: #define RESPONSE_BODY_SIZE 128 7:  8: static size_t write_function(const void *buffer, const size_t size, const size_t nmemb, void *user_p) 9: {10:     char* response_body = (char*)user_p;11:     uint32_t response_body_len = strlen(response_body);12:     uint32_t len = size*nmemb;13:     if (len > RESPONSE_BODY_SIZE - response_body_len - 1) {14:         len = RESPONSE_BODY_SIZE - response_body_len - 1;15:     }16:     memcpy(response_body + response_body_len, buffer, len);17:     return size*nmemb;18: }19: 20: int main(int argc, char *argv[])21: {22:     const char* url = "http://www.example.com/dns_servers";23:     struct curl_slist *headers = NULL;24:     headers = curl_slist_append(headers, "Content-Type: application/json");25:     const char* request_body = "{\"host\": \"8.8.8.8\", \"port\": 53}";26: 27:     CURL *curl;28:     CURLcode res;29:     char response_body[RESPONSE_BODY_SIZE] = {'\0'};30:     long response_code = 0;31: 32:     curl = curl_easy_init();33:     if(curl) {34:         curl_easy_setopt(curl, CURLOPT_URL, url);35:         curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);36:         curl_easy_setopt(curl, CURLOPT_POSTFIELDS, request_body);37:         curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE, strlen(request_body));38:         curl_easy_setopt(curl, CURLOPT_NOSIGNAL, 1L);39:         curl_easy_setopt(curl, CURLOPT_TIMEOUT, 10L);40:         curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_function);41:         curl_easy_setopt(curl, CURLOPT_WRITEDATA, response_body);42:         res = curl_easy_perform(curl);43:         if (res == CURLE_OK) {44:             res = curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &response_code);45:         }46:         if(res != CURLE_OK) {47:             fprintf(stderr, "request to %s error(%d): %s", url, res, curl_easy_strerror(res));48:         }49:         curl_easy_cleanup(curl);50:     }51: 52:     curl_slist_free_all(headers);53:     if (response_code == 201) {54:         fprintf(stderr, "request to %s successful: %s\n", url, response_body);55:         return 0;56:     }57: 58:     fprintf(stderr, "request to %s response failed(%ld): %s\n", url, response_code, response_body);59:     return 1;60: }

上面的示例代码要注意的地方:

行 16
buffer不是 \0 结尾的
行 17
总是返回 size*nmemb
行 38
总是设置这个选项

libcurl 不支持异步 dns 解析时,会通过 signal 的方式实现 dns 解析设置超时, signal 会导致多线程程序崩溃,后台服务通常都是多线程的,所以应该总是设置这个选项(但是 libcurl 不支持异步 dns 解析时,超时选项将被忽略)。

可以通过运行 curl --version 命令或调用 curl_version 函数查看 libcurl 是否支持异步 dns 解析,调用 curl_version_info 函数还可以获得具体的 c-ares 库版本号。

编译 libcurl 时,通过为 configure 指定 --enable-threaded-resolver 或 --enable-ares 选项启用异步 dns 解析。

行 44
状态响应码变量必须是 long 类型

否则会由于内存越界导致程序崩溃。


0 0
原创粉丝点击