From d4a96fedf610d74e46391bfabdf60914faceda15 Mon Sep 17 00:00:00 2001 From: William Douglas Date: Thu, 28 Apr 2016 17:14:08 +0000 Subject: [PATCH] Fix version to memory download In the case where the swupd_download_version_to_memory callback was run multiple times, it would overwrite previous data instead of appending. Correct this behavior by keeping track of data written so far in the struct passed to the callback. --- Makefile.am | 1 + src/curl.c | 19 ++++++++--- src/version.c | 2 +- .../checkupdate/slow-server/server.py | 25 ++++++++++++++ .../slow-server/target-dir/usr/lib/os-release | 9 +++++ .../checkupdate/slow-server/test.bats | 34 +++++++++++++++++++ 6 files changed, 84 insertions(+), 6 deletions(-) create mode 100755 test/functional/checkupdate/slow-server/server.py create mode 100644 test/functional/checkupdate/slow-server/target-dir/usr/lib/os-release create mode 100755 test/functional/checkupdate/slow-server/test.bats diff --git a/Makefile.am b/Makefile.am index 30145e07..38c93a82 100644 --- a/Makefile.am +++ b/Makefile.am @@ -152,6 +152,7 @@ dist_check_SCRIPTS = \ test/functional/checkupdate/new-version/test.bats \ test/functional/checkupdate/no-server-content/test.bats \ test/functional/checkupdate/no-target-content/test.bats \ + test/functional/checkupdate/slow-server/test.bats \ test/functional/checkupdate/version-match/test.bats \ test/functional/hashdump/file-hash/test.bats \ test/functional/hashdump/file-hash-no-path-prefix/test.bats \ diff --git a/src/curl.c b/src/curl.c index 5a54133d..1103e324 100644 --- a/src/curl.c +++ b/src/curl.c @@ -51,6 +51,11 @@ static CURL *curl = NULL; static int curr_version = -1; static int req_version = -1; +struct version_container { + size_t offset; + char *version; +}; + int swupd_curl_init(void) { CURLcode curl_ret; @@ -143,15 +148,16 @@ double swupd_query_url_content_size(char *url) static size_t swupd_download_version_to_memory(void *ptr, size_t size, size_t nmemb, void *userdata) { - char *tmp_version = (char *)userdata; + struct version_container *tmp_version = (struct version_container *)userdata; size_t data_len = size * nmemb; - if (data_len >= LINE_MAX) { + if (data_len + tmp_version->offset >= LINE_MAX) { return 0; } - memcpy(tmp_version, ptr, data_len); - tmp_version[data_len] = '\0'; + memcpy(tmp_version->version + tmp_version->offset, ptr, data_len); + tmp_version->version[data_len + tmp_version->offset] = '\0'; + tmp_version->offset += data_len; return data_len; } @@ -251,6 +257,9 @@ int swupd_curl_get_file(const char *url, char *filename, struct file *file, goto exit; } } else { + struct version_container vc = { 0 }; + vc.version = in_memory_version_string; + // only download latest version number, storing in the provided pointer printf("Attempting to download version string to memory\n"); @@ -258,7 +267,7 @@ int swupd_curl_get_file(const char *url, char *filename, struct file *file, if (curl_ret != CURLE_OK) { goto exit; } - curl_ret = curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void *)in_memory_version_string); + curl_ret = curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void *)&vc); if (curl_ret != CURLE_OK) { goto exit; } diff --git a/src/version.c b/src/version.c index 090be2e6..23a5eab1 100644 --- a/src/version.c +++ b/src/version.c @@ -41,7 +41,7 @@ int get_latest_version(void) int ret = 0; char *tmp_version; - tmp_version = malloc(LINE_MAX); + tmp_version = calloc(LINE_MAX, 1); if (tmp_version == NULL) { abort(); } diff --git a/test/functional/checkupdate/slow-server/server.py b/test/functional/checkupdate/slow-server/server.py new file mode 100755 index 00000000..89234c0a --- /dev/null +++ b/test/functional/checkupdate/slow-server/server.py @@ -0,0 +1,25 @@ +#!/usr/bin/env python3 + +import http.server as server +import sys +import time + + +class SlowResponse(server.BaseHTTPRequestHandler): + """Handler that returns data with a set delay between writes""" + def do_GET(self): + self.send_response(200) + self.send_header("Content-type", "text/html") + self.end_headers() + response = "99990" + delay = 0.00001 # seconds + for c in response: + self.wfile.write(str.encode(c)) + time.sleep(delay) + + +if __name__ == '__main__': + print(sys.argv) + addr = ('', int(sys.argv[1])) + httpd = server.HTTPServer(addr, SlowResponse) + httpd.serve_forever() diff --git a/test/functional/checkupdate/slow-server/target-dir/usr/lib/os-release b/test/functional/checkupdate/slow-server/target-dir/usr/lib/os-release new file mode 100644 index 00000000..d20f3873 --- /dev/null +++ b/test/functional/checkupdate/slow-server/target-dir/usr/lib/os-release @@ -0,0 +1,9 @@ +NAME="Clear Linux Software for Intel Architecture" +VERSION=1 +ID=clear-linux-os +VERSION_ID=10 +PRETTY_NAME="Clear Linux Software for Intel Architecture" +ANSI_COLOR="1;35" +HOME_URL="https://clearlinux.org" +SUPPORT_URL="https://clearlinux.org" +BUG_REPORT_URL="https://bugs.clearlinux.org/jira" diff --git a/test/functional/checkupdate/slow-server/test.bats b/test/functional/checkupdate/slow-server/test.bats new file mode 100755 index 00000000..a81fb2f0 --- /dev/null +++ b/test/functional/checkupdate/slow-server/test.bats @@ -0,0 +1,34 @@ +#!/usr/bin/env bats + +load "../../swupdlib" + +server_pid="" +port="" + +setup() { + for i in $(seq 8080 8180); do + "$DIR/server.py" $i & + sleep .2 + server_pid=$! + if [ -d /proc/$server_pid ]; then + port=$i + break + fi + done +} + +teardown() { + kill $server_pid +} + +@test "check-update with a slow server" { + slow_opts="-p $DIR/target-dir -F staging -u http://localhost:$port/" + run sudo sh -c "$SWUPD check-update $slow_opts" + + echo "$output" + [ "${lines[2]}" = "Querying server version." ] + [ "${lines[3]}" = "Attempting to download version string to memory" ] + [ "${lines[4]}" = "There is a new OS version available: 99990" ] +} + +# vi: ft=sh ts=8 sw=2 sts=2 et tw=80