diff options
author | Timo Teräs <timo.teras@iki.fi> | 2021-07-16 10:54:08 +0300 |
---|---|---|
committer | Timo Teräs <timo.teras@iki.fi> | 2021-07-26 14:43:35 +0300 |
commit | 36048e8fef019c5be938f8a688845b6eef1d46ab (patch) | |
tree | 0aa34f757463289276b3ccacc5395fdc5decca85 /libfetch/ftp.c | |
parent | 41a6e4c247e68e906bea1ca7c31f0e8d3b49bc83 (diff) | |
download | apk-tools-36048e8fef019c5be938f8a688845b6eef1d46ab.tar.gz apk-tools-36048e8fef019c5be938f8a688845b6eef1d46ab.tar.bz2 apk-tools-36048e8fef019c5be938f8a688845b6eef1d46ab.tar.xz apk-tools-36048e8fef019c5be938f8a688845b6eef1d46ab.zip |
libfetch: fix range checking for http/ftp protocol parsing
Various parsing of numeric strings were not having adequate range
checking causing information leak or potential crash.
CVE-2021-36159
fixes #10749
Co-authored-by: Ariadne Conill <ariadne@dereferenced.org>
Reported-by: Samanta Navarro <ferivoz@riseup.net>
Diffstat (limited to 'libfetch/ftp.c')
-rw-r--r-- | libfetch/ftp.c | 18 |
1 files changed, 11 insertions, 7 deletions
diff --git a/libfetch/ftp.c b/libfetch/ftp.c index 8f9f04f..77790aa 100644 --- a/libfetch/ftp.c +++ b/libfetch/ftp.c @@ -471,8 +471,7 @@ ftp_stat(conn_t *conn, const char *file, struct url_stat *us) } for (ln = conn->buf + 4; *ln && isspace((unsigned char)*ln); ln++) /* nothing */ ; - for (us->size = 0; *ln && isdigit((unsigned char)*ln); ln++) - us->size = us->size * 10 + *ln - '0'; + us->size = fetch_parseuint(ln, (const char **) &ln, 10, OFF_MAX); if (*ln && !isspace((unsigned char)*ln)) { ftp_seterr(FTP_PROTOCOL_ERROR); us->size = -1; @@ -700,7 +699,7 @@ retry_mode: if (pasv) { unsigned char addr[64]; - char *ln, *p; + const char *ln, *p; unsigned int i; int port; @@ -737,10 +736,15 @@ retry_mode: for (p = ln + 3; *p && !isdigit((unsigned char)*p); p++) /* nothing */ ; if (!*p) goto protocol_error; - l = (e == FTP_PASSIVE_MODE ? 6 : 21); - for (i = 0; *p && i < l; i++, p++) - addr[i] = strtol(p, &p, 10); - if (i < l) goto protocol_error; + l = (e == FTP_PASSIVE_MODE ? 6 : 21) - 1; + for (i = 0; *p && i < l; i++, p++) { + while (isspace((unsigned char)*p)) p++; + addr[i] = fetch_parseuint(p, &p, 10, UCHAR_MAX); + if (*p != ',') goto protocol_error; + } + while (isspace((unsigned char)*p)) p++; + addr[i] = fetch_parseuint(p, &p, 10, UCHAR_MAX); + if (*p && *p != ')') goto protocol_error; break; case FTP_EPASSIVE_MODE: for (p = ln + 3; *p && *p != '('; p++) |