From feb2dd283533f842c9b6e4cc2fcc7fd35638d5a0 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Thu, 24 Jun 2004 11:54:11 +0000 Subject: Replaced all uses of sprintf() with the safer snprintf(). It is just a precaution to prevent mistakes to lead to buffer overflows. --- lib/base64.c | 24 +- lib/escape.c | 2 +- lib/file.c | 7 +- lib/formdata.c | 2 +- lib/ftp.c | 11 +- lib/hostip.c | 27 +- lib/http_digest.c | 2 +- lib/http_negotiate.c | 38 +-- lib/inet_ntop.c | 5 +- lib/mprintf.c | 801 ++++++++++++++++++++++++++------------------------- lib/progress.c | 35 +-- lib/ssluse.c | 4 +- lib/version.c | 78 +++-- 13 files changed, 520 insertions(+), 516 deletions(-) diff --git a/lib/base64.c b/lib/base64.c index 987835b4f..2416bca06 100644 --- a/lib/base64.c +++ b/lib/base64.c @@ -160,22 +160,22 @@ size_t Curl_base64_encode(const char *inp, size_t insize, char **outptr) switch(inputparts) { case 1: /* only one byte read */ - sprintf(output, "%c%c==", - table64[obuf[0]], - table64[obuf[1]]); + snprintf(output, 5, "%c%c==", + table64[obuf[0]], + table64[obuf[1]]); break; case 2: /* two bytes read */ - sprintf(output, "%c%c%c=", - table64[obuf[0]], - table64[obuf[1]], - table64[obuf[2]]); + snprintf(output, 5, "%c%c%c=", + table64[obuf[0]], + table64[obuf[1]], + table64[obuf[2]]); break; default: - sprintf(output, "%c%c%c%c", - table64[obuf[0]], - table64[obuf[1]], - table64[obuf[2]], - table64[obuf[3]] ); + snprintf(output, 5, "%c%c%c%c", + table64[obuf[0]], + table64[obuf[1]], + table64[obuf[2]], + table64[obuf[3]] ); break; } output += 4; diff --git a/lib/escape.c b/lib/escape.c index 600cece7c..00e2fae6e 100644 --- a/lib/escape.c +++ b/lib/escape.c @@ -68,7 +68,7 @@ char *curl_escape(const char *string, int length) ns = testing_ptr; } } - sprintf(&ns[strindex], "%%%02X", in); + snprintf(&ns[strindex], 4, "%%%02X", in); strindex+=3; } diff --git a/lib/file.c b/lib/file.c index 8f47a19e6..7bbf8a340 100644 --- a/lib/file.c +++ b/lib/file.c @@ -300,13 +300,14 @@ CURLcode Curl_file(struct connectdata *conn) date. */ if(conn->bits.no_body && data->set.include_header && fstated) { CURLcode result; - sprintf(buf, "Content-Length: %" FORMAT_OFF_T "\r\n", expected_size); + snprintf(buf, sizeof(data->state.buffer), + "Content-Length: %" FORMAT_OFF_T "\r\n", expected_size); result = Curl_client_write(data, CLIENTWRITE_BOTH, buf, 0); if(result) return result; - sprintf(buf, "Accept-ranges: bytes\r\n"); - result = Curl_client_write(data, CLIENTWRITE_BOTH, buf, 0); + result = Curl_client_write(data, CLIENTWRITE_BOTH, + "Accept-ranges: bytes\r\n", 0); if(result) return result; diff --git a/lib/formdata.c b/lib/formdata.c index c338052da..9c7fc8be2 100644 --- a/lib/formdata.c +++ b/lib/formdata.c @@ -846,7 +846,7 @@ static CURLcode AddFormDataf(struct FormData **formp, char s[4096]; va_list ap; va_start(ap, fmt); - vsprintf(s, fmt, ap); + vsnprintf(s, sizeof(s), fmt, ap); va_end(ap); return AddFormData(formp, FORM_DATA, s, 0, size); diff --git a/lib/ftp.c b/lib/ftp.c index fc987faf0..ad9fb6054 100644 --- a/lib/ftp.c +++ b/lib/ftp.c @@ -932,8 +932,9 @@ CURLcode ftp_getfiletime(struct connectdata *conn, char *file) &year, &month, &day, &hour, &minute, &second)) { /* we have a time, reformat it */ time_t secs=time(NULL); - sprintf(buf, "%04d%02d%02d %02d:%02d:%02d GMT", - year, month, day, hour, minute, second); + snprintf(buf, sizeof(conn->data->state.buffer), + "%04d%02d%02d %02d:%02d:%02d GMT", + year, month, day, hour, minute, second); /* now, convert this into a time() value: */ conn->data->info.filetime = curl_getdate(buf, &secs); } @@ -1506,7 +1507,8 @@ CURLcode ftp_use_pasv(struct connectdata *conn, return CURLE_FTP_WEIRD_227_FORMAT; } - sprintf(newhost, "%d.%d.%d.%d", ip[0], ip[1], ip[2], ip[3]); + snprintf(newhost, sizeof(newhost), + "%d.%d.%d.%d", ip[0], ip[1], ip[2], ip[3]); newhostp = newhost; newport = (port[0]<<8) + port[1]; } @@ -2161,7 +2163,8 @@ CURLcode ftp_perform(struct connectdata *conn, result = ftp_getsize(conn, ftp->file, &filesize); if(CURLE_OK == result) { - sprintf(buf, "Content-Length: %" FORMAT_OFF_T "\r\n", filesize); + snprintf(buf, sizeof(data->state.buffer), + "Content-Length: %" FORMAT_OFF_T "\r\n", filesize); result = Curl_client_write(data, CLIENTWRITE_BOTH, buf, 0); if(result) return result; diff --git a/lib/hostip.c b/lib/hostip.c index 7a32d1728..0612d2f93 100644 --- a/lib/hostip.c +++ b/lib/hostip.c @@ -228,24 +228,10 @@ static int _num_chars(int i) * the DNS caching. */ static char * -create_hostcache_id(char *server, int port, size_t *entry_len) +create_hostcache_id(char *server, int port) { - char *id = NULL; - - /* Get the length of the new entry id */ - *entry_len = strlen(server) + /* Hostname length */ - 1 + /* ':' seperator */ - _num_chars(port); /* number of characters the port will take up */ - - /* Allocate the new entry id */ - id = malloc(*entry_len + 1); /* 1 extra for the zero terminator */ - if (!id) - return NULL; - - /* Create the new entry */ - sprintf(id, "%s:%d", server, port); - - return id; /* return pointer to the string */ + /* create and return the new allocated entry */ + return aprintf("%s:%d", server, port); } struct hostcache_prune_data { @@ -349,10 +335,11 @@ Curl_cache_addr(struct SessionHandle *data, time_t now; /* Create an entry id, based upon the hostname and port */ - entry_id = create_hostcache_id(hostname, port, &entry_len); + entry_id = create_hostcache_id(hostname, port); /* If we can't create the entry id, fail */ if (!entry_id) return NULL; + entry_len = strlen(entry_id); /* Create a new cache entry */ dns = (struct Curl_dns_entry *) malloc(sizeof(struct Curl_dns_entry)); @@ -430,11 +417,13 @@ int Curl_resolv(struct connectdata *conn, #endif /* Create an entry id, based upon the hostname and port */ - entry_id = create_hostcache_id(hostname, port, &entry_len); + entry_id = create_hostcache_id(hostname, port); /* If we can't create the entry id, fail */ if (!entry_id) return CURLRESOLV_ERROR; + entry_len = strlen(entry_id); + if(data->share) Curl_share_lock(data, CURL_LOCK_DATA_DNS, CURL_LOCK_ACCESS_SINGLE); diff --git a/lib/http_digest.c b/lib/http_digest.c index b98af6803..d06453e8a 100644 --- a/lib/http_digest.c +++ b/lib/http_digest.c @@ -201,7 +201,7 @@ static void md5_to_ascii(unsigned char *source, /* 16 bytes */ { int i; for(i=0; i<16; i++) - sprintf((char *)&dest[i*2], "%02x", source[i]); + snprintf((char *)&dest[i*2], 3, "%02x", source[i]); } CURLcode Curl_output_digest(struct connectdata *conn, diff --git a/lib/http_negotiate.c b/lib/http_negotiate.c index ece40692b..71bd3513a 100644 --- a/lib/http_negotiate.c +++ b/lib/http_negotiate.c @@ -1,8 +1,8 @@ /*************************************************************************** - * _ _ ____ _ - * Project ___| | | | _ \| | - * / __| | | | |_) | | - * | (__| |_| | _ <| |___ + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * * Copyright (C) 1998 - 2004, Daniel Stenberg, , et al. @@ -10,7 +10,7 @@ * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms * are also available at http://curl.haxx.se/docs/copyright.html. - * + * * You may opt to use, copy, modify, merge, publish, distribute and/or sell * copies of the Software, and permit persons to whom the Software is * furnished to do so, under the terms of the COPYING file. @@ -28,7 +28,7 @@ #endif #ifndef CURL_DISABLE_HTTP -/* -- WIN32 approved -- */ + /* -- WIN32 approved -- */ #include #include #include @@ -64,8 +64,8 @@ get_gss_name(struct connectdata *conn, gss_name_t *server) Change following lines if you want to use GSI */ /* IIS uses the @ form but uses 'http' as the service name */ - - if (neg_ctx->gss) + + if (neg_ctx->gss) service = "khttp"; else service = "http"; @@ -73,7 +73,8 @@ get_gss_name(struct connectdata *conn, gss_name_t *server) token.length = strlen(service) + 1 + strlen(conn->host.name) + 1; if (token.length + 1 > sizeof(name)) return EMSGSIZE; - sprintf(name, "%s@%s", service, conn->host.name); + + snprintf(name, sizeof(name), "%s@%s", service, conn->host.name); token.value = (void *) name; major_status = gss_import_name(&minor_status, @@ -102,8 +103,9 @@ log_gss_error(struct connectdata *conn, OM_uint32 error_status, char *prefix) GSS_C_NO_OID, &msg_ctx, &status_string); - if (sizeof(buf) > len + status_string.length + 1) { - sprintf(buf + len, ": %s", (char*) status_string.value); + if (sizeof(buf) > len + status_string.length + 1) { + snprintf(buf + len, sizeof(buf) - len, + ": %s", (char*) status_string.value); len += status_string.length; } gss_release_buffer(&min_stat, &status_string); @@ -113,7 +115,7 @@ log_gss_error(struct connectdata *conn, OM_uint32 error_status, char *prefix) } int Curl_input_negotiate(struct connectdata *conn, char *header) -{ +{ struct negotiatedata *neg_ctx = &conn->data->state.negotiate; OM_uint32 major_status, minor_status, minor_status2; gss_buffer_desc input_token = GSS_C_EMPTY_BUFFER; @@ -145,7 +147,7 @@ int Curl_input_negotiate(struct connectdata *conn, char *header) neg_ctx->protocol = protocol; neg_ctx->gss = gss; } - + if (neg_ctx->context && neg_ctx->status == GSS_S_COMPLETE) { /* We finished succesfully our part of authentication, but server * rejected it (since we're again here). Exit with an error since we @@ -247,10 +249,10 @@ int Curl_input_negotiate(struct connectdata *conn, char *header) return 0; } - + CURLcode Curl_output_negotiate(struct connectdata *conn) -{ +{ struct negotiatedata *neg_ctx = &conn->data->state.negotiate; OM_uint32 minor_status; char *encoded = NULL; @@ -264,7 +266,7 @@ CURLcode Curl_output_negotiate(struct connectdata *conn) size_t spnegoTokenLength = 0; unsigned char * responseToken = NULL; size_t responseTokenLength = 0; - + responseToken = malloc(neg_ctx->output_token.length); if ( responseToken == NULL) return CURLE_OUT_OF_MEMORY; @@ -309,7 +311,7 @@ CURLcode Curl_output_negotiate(struct connectdata *conn) } void Curl_cleanup_negotiate(struct SessionHandle *data) -{ +{ OM_uint32 minor_status; struct negotiatedata *neg_ctx = &data->state.negotiate; @@ -321,7 +323,7 @@ void Curl_cleanup_negotiate(struct SessionHandle *data) if (neg_ctx->server_name != GSS_C_NO_NAME) gss_release_name(&minor_status, &neg_ctx->server_name); - + memset(neg_ctx, 0, sizeof(*neg_ctx)); } diff --git a/lib/inet_ntop.c b/lib/inet_ntop.c index 9dfccb3c6..eec06073b 100644 --- a/lib/inet_ntop.c +++ b/lib/inet_ntop.c @@ -24,6 +24,9 @@ #include #include +#define _MPRINTF_REPLACE /* use our functions only */ +#include + #include "inet_ntop.h" #if defined(HAVE_INET_NTOA_R) && !defined(HAVE_INET_NTOA_R_DECL) @@ -152,7 +155,7 @@ static const char *inet_ntop6 (const u_char *src, char *dst, size_t size) tp += strlen(tp); break; } - tp += sprintf (tp, "%lx", words[i]); + tp += snprintf(tp, 4, "%lx", words[i]); } /* Was it a trailing run of 0x00's? diff --git a/lib/mprintf.c b/lib/mprintf.c index 6e77075c2..9135a1308 100644 --- a/lib/mprintf.c +++ b/lib/mprintf.c @@ -82,7 +82,7 @@ static const char lower_digits[] = "0123456789abcdefghijklmnopqrstuvwxyz"; /* Upper-case digits. */ static const char upper_digits[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"; -#define OUTCHAR(x) \ +#define OUTCHAR(x) \ do{ \ if(stream((unsigned char)(x), (FILE *)data) != -1) \ done++; \ @@ -234,45 +234,45 @@ int dprintf_Pass1Report(va_stack_t *vto, int max) flags = vto[i].flags & (1< max_param) - max_param = this_param; + max_param = this_param; /* * The parameter with number 'i' should be used. Next, we need @@ -335,59 +335,59 @@ static long dprintf_Pass1(char *format, va_stack_t *vto, char **endpos, /* Handle the flags */ while (dprintf_IsQualifierNoDollar(*fmt)) { - switch (*fmt++) { - case ' ': - flags |= FLAGS_SPACE; - break; - case '+': - flags |= FLAGS_SHOWSIGN; - break; - case '-': - flags |= FLAGS_LEFT; - flags &= ~FLAGS_PAD_NIL; - break; - case '#': - flags |= FLAGS_ALT; - break; - case '.': - flags |= FLAGS_PREC; - if ('*' == *fmt) { - /* The precision is picked from a specified parameter */ - - flags |= FLAGS_PRECPARAM; - fmt++; - param_num++; - - i = dprintf_DollarString(fmt, &fmt); - if (i) - precision = i; - else - precision = param_num; - - if (precision > max_param) - max_param = precision; - } - else { - flags |= FLAGS_PREC; - precision = strtol(fmt, &fmt, 10); - } - break; - case 'h': - flags |= FLAGS_SHORT; - break; - case 'l': - if (flags & FLAGS_LONG) - flags |= FLAGS_LONGLONG; - else - flags |= FLAGS_LONG; - break; - case 'L': - flags |= FLAGS_LONGDOUBLE; - break; - case 'q': - flags |= FLAGS_LONGLONG; - break; - case 'z': + switch (*fmt++) { + case ' ': + flags |= FLAGS_SPACE; + break; + case '+': + flags |= FLAGS_SHOWSIGN; + break; + case '-': + flags |= FLAGS_LEFT; + flags &= ~FLAGS_PAD_NIL; + break; + case '#': + flags |= FLAGS_ALT; + break; + case '.': + flags |= FLAGS_PREC; + if ('*' == *fmt) { + /* The precision is picked from a specified parameter */ + + flags |= FLAGS_PRECPARAM; + fmt++; + param_num++; + + i = dprintf_DollarString(fmt, &fmt); + if (i) + precision = i; + else + precision = param_num; + + if (precision > max_param) + max_param = precision; + } + else { + flags |= FLAGS_PREC; + precision = strtol(fmt, &fmt, 10); + } + break; + case 'h': + flags |= FLAGS_SHORT; + break; + case 'l': + if (flags & FLAGS_LONG) + flags |= FLAGS_LONGLONG; + else + flags |= FLAGS_LONG; + break; + case 'L': + flags |= FLAGS_LONGDOUBLE; + break; + case 'q': + flags |= FLAGS_LONGLONG; + break; + case 'z': /* the code below generates a warning if -Wunreachable-code is used */ #if SIZEOF_SIZE_T>4 @@ -403,30 +403,30 @@ static long dprintf_Pass1(char *format, va_stack_t *vto, char **endpos, flags |= FLAGS_LONG; #endif break; - case '0': - if (!(flags & FLAGS_LEFT)) - flags |= FLAGS_PAD_NIL; - /* FALLTHROUGH */ - case '1': case '2': case '3': case '4': - case '5': case '6': case '7': case '8': case '9': - flags |= FLAGS_WIDTH; - width = strtol(fmt-1, &fmt, 10); - break; - case '*': /* Special case */ - flags |= FLAGS_WIDTHPARAM; - param_num++; - - i = dprintf_DollarString(fmt, &fmt); - if(i) - width = i; - else - width = param_num; - if(width > max_param) - max_param=width; - break; - default: - break; - } + case '0': + if (!(flags & FLAGS_LEFT)) + flags |= FLAGS_PAD_NIL; + /* FALLTHROUGH */ + case '1': case '2': case '3': case '4': + case '5': case '6': case '7': case '8': case '9': + flags |= FLAGS_WIDTH; + width = strtol(fmt-1, &fmt, 10); + break; + case '*': /* Special case */ + flags |= FLAGS_WIDTHPARAM; + param_num++; + + i = dprintf_DollarString(fmt, &fmt); + if(i) + width = i; + else + width = param_num; + if(width > max_param) + max_param=width; + break; + default: + break; + } } /* switch */ /* Handle the specifier */ @@ -435,62 +435,62 @@ static long dprintf_Pass1(char *format, va_stack_t *vto, char **endpos, switch (*fmt) { case 'S': - flags |= FLAGS_ALT; - /* FALLTHROUGH */ + flags |= FLAGS_ALT; + /* FALLTHROUGH */ case 's': - vto[i].type = FORMAT_STRING; - break; + vto[i].type = FORMAT_STRING; + break; case 'n': - vto[i].type = FORMAT_INTPTR; - break; + vto[i].type = FORMAT_INTPTR; + break; case 'p': - vto[i].type = FORMAT_PTR; - break; + vto[i].type = FORMAT_PTR; + break; case 'd': case 'i': - vto[i].type = FORMAT_INT; - break; + vto[i].type = FORMAT_INT; + break; case 'u': - vto[i].type = FORMAT_INT; - flags |= FLAGS_UNSIGNED; - break; + vto[i].type = FORMAT_INT; + flags |= FLAGS_UNSIGNED; + break; case 'o': - vto[i].type = FORMAT_INT; - flags |= FLAGS_OCTAL; - break; + vto[i].type = FORMAT_INT; + flags |= FLAGS_OCTAL; + break; case 'x': - vto[i].type = FORMAT_INT; - flags |= FLAGS_HEX; - break; + vto[i].type = FORMAT_INT; + flags |= FLAGS_HEX; + break; case 'X': - vto[i].type = FORMAT_INT; - flags |= FLAGS_HEX|FLAGS_UPPER; - break; + vto[i].type = FORMAT_INT; + flags |= FLAGS_HEX|FLAGS_UPPER; + break; case 'c': - vto[i].type = FORMAT_INT; - flags |= FLAGS_CHAR; - break; + vto[i].type = FORMAT_INT; + flags |= FLAGS_CHAR; + break; case 'f': - vto[i].type = FORMAT_DOUBLE; - break; + vto[i].type = FORMAT_DOUBLE; + break; case 'e': - vto[i].type = FORMAT_DOUBLE; - flags |= FLAGS_FLOATE; - break; + vto[i].type = FORMAT_DOUBLE; + flags |= FLAGS_FLOATE; + break; case 'E': - vto[i].type = FORMAT_DOUBLE; - flags |= FLAGS_FLOATE|FLAGS_UPPER; - break; + vto[i].type = FORMAT_DOUBLE; + flags |= FLAGS_FLOATE|FLAGS_UPPER; + break; case 'g': - vto[i].type = FORMAT_DOUBLE; - flags |= FLAGS_FLOATG; - break; + vto[i].type = FORMAT_DOUBLE; + flags |= FLAGS_FLOATG; + break; case 'G': - vto[i].type = FORMAT_DOUBLE; - flags |= FLAGS_FLOATG|FLAGS_UPPER; - break; + vto[i].type = FORMAT_DOUBLE; + flags |= FLAGS_FLOATG|FLAGS_UPPER; + break; default: - vto[i].type = FORMAT_UNKNOWN; - break; + vto[i].type = FORMAT_UNKNOWN; + break; } /* switch */ vto[i].flags = flags; @@ -498,24 +498,24 @@ static long dprintf_Pass1(char *format, va_stack_t *vto, char **endpos, vto[i].precision = precision; if (flags & FLAGS_WIDTHPARAM) { - /* we have the width specified from a parameter, so we make that - parameter's info setup properly */ - vto[i].width = width - 1; - i = width - 1; - vto[i].type = FORMAT_WIDTH; - vto[i].flags = FLAGS_NEW; - vto[i].precision = vto[i].width = 0; /* can't use width or precision - of width! */ + /* we have the width specified from a parameter, so we make that + parameter's info setup properly */ + vto[i].width = width - 1; + i = width - 1; + vto[i].type = FORMAT_WIDTH; + vto[i].flags = FLAGS_NEW; + vto[i].precision = vto[i].width = 0; /* can't use width or precision + of width! */ } if (flags & FLAGS_PRECPARAM) { - /* we have the precision specified from a parameter, so we make that - parameter's info setup properly */ - vto[i].precision = precision - 1; - i = precision - 1; - vto[i].type = FORMAT_WIDTH; - vto[i].flags = FLAGS_NEW; - vto[i].precision = vto[i].width = 0; /* can't use width or precision - of width! */ + /* we have the precision specified from a parameter, so we make that + parameter's info setup properly */ + vto[i].precision = precision - 1; + i = precision - 1; + vto[i].type = FORMAT_WIDTH; + vto[i].flags = FLAGS_NEW; + vto[i].precision = vto[i].width = 0; /* can't use width or precision + of width! */ } *endpos++ = fmt + 1; /* end of this sequence */ } @@ -529,49 +529,49 @@ static long dprintf_Pass1(char *format, va_stack_t *vto, char **endpos, for (i=0; idata.num; if(p->flags & FLAGS_CHAR) { - /* Character. */ - if (!(p->flags & FLAGS_LEFT)) - while (--width > 0) - OUTCHAR(' '); - OUTCHAR((char) num); - if (p->flags & FLAGS_LEFT) - while (--width > 0) - OUTCHAR(' '); - break; + /* Character. */ + if (!(p->flags & FLAGS_LEFT)) + while (--width > 0) + OUTCHAR(' '); + OUTCHAR((char) num); + if (p->flags & FLAGS_LEFT) + while (--width > 0) + OUTCHAR(' '); + break; } if(p->flags & FLAGS_UNSIGNED) { - /* Decimal unsigned integer. */ - base = 10; - goto unsigned_number; + /* Decimal unsigned integer. */ + base = 10; + goto unsigned_number; } if(p->flags & FLAGS_OCTAL) { - /* Octal unsigned integer. */ - base = 8; - goto unsigned_number; + /* Octal unsigned integer. */ + base = 8; + goto unsigned_number; } if(p->flags & FLAGS_HEX) { - /* Hexadecimal unsigned integer. */ + /* Hexadecimal unsigned integer. */ - digits = (p->flags & FLAGS_UPPER)? upper_digits : lower_digits; - base = 16; - goto unsigned_number; + digits = (p->flags & FLAGS_UPPER)? upper_digits : lower_digits; + base = 16; + goto unsigned_number; } /* Decimal integer. */ @@ -727,223 +727,230 @@ static int dprintf_formatf( #ifdef ENABLE_64BIT if(p->flags & FLAGS_LONGLONG) { /* long long */ - is_neg = p->data.lnum < 0; - num = is_neg ? (- p->data.lnum) : p->data.lnum; + is_neg = p->data.lnum < 0; + num = is_neg ? (- p->data.lnum) : p->data.lnum; } else #endif { - signed_num = (long) num; - - is_neg = signed_num < 0; - num = is_neg ? (- signed_num) : signed_num; + signed_num = (long) num; + is_neg = signed_num < 0; + num = is_neg ? (- signed_num) : signed_num; } goto number; - unsigned_number:; + unsigned_number: /* Unsigned number of base BASE. */ is_neg = 0; - number:; + number: /* Number of base BASE. */ { - char *workend = &work[sizeof(work) - 1]; - char *w; - - /* Supply a default precision if none was given. */ - if (prec == -1) - prec = 1; - - /* Put the number in WORK. */ - w = workend; - while (num > 0) { - *w-- = digits[num % base]; - num /= base; - } - width -= workend - w; - prec -= workend - w; - - if (alt && base == 8 && prec <= 0) { - *w-- = '0'; - --width; - } - - if (prec > 0) { - width -= prec; - while (prec-- > 0) - *w-- = '0'; - } - - if (alt && base == 16) - width -= 2; - - if (is_neg || (p->flags & FLAGS_SHOWSIGN) || (p->flags & FLAGS_SPACE)) - --width; - - if (!(p->flags & FLAGS_LEFT) && !(p->flags & FLAGS_PAD_NIL)) - while (width-- > 0) - OUTCHAR(' '); - - if (is_neg) - OUTCHAR('-'); - else if (p->flags & FLAGS_SHOWSIGN) - OUTCHAR('+'); - else if (p->flags & FLAGS_SPACE) - OUTCHAR(' '); - - if (alt && base == 16) { - OUTCHAR('0'); - if(p->flags & FLAGS_UPPER) - OUTCHAR('X'); - else - OUTCHAR('x'); - } - - if (!(p->flags & FLAGS_LEFT) && (p->flags & FLAGS_PAD_NIL)) - while (width-- > 0) - OUTCHAR('0'); - - /* Write the number. */ - while (++w <= workend) { - OUTCHAR(*w); - } - - if (p->flags & FLAGS_LEFT) - while (width-- > 0) - OUTCHAR(' '); + char *workend = &work[sizeof(work) - 1]; + char *w; + + /* Supply a default precision if none was given. */ + if (prec == -1) + prec = 1; + + /* Put the number in WORK. */ + w = workend; + while (num > 0) { + *w-- = digits[num % base]; + num /= base; + } + width -= workend - w; + prec -= workend - w; + + if (alt && base == 8 && prec <= 0) { + *w-- = '0'; + --width; + } + + if (prec > 0) { + width -= prec; + while (prec-- > 0) + *w-- = '0'; + } + + if (alt && base == 16) + width -= 2; + + if (is_neg || (p->flags & FLAGS_SHOWSIGN) || (p->flags & FLAGS_SPACE)) + --width; + + if (!(p->flags & FLAGS_LEFT) && !(p->flags & FLAGS_PAD_NIL)) + while (width-- > 0) + OUTCHAR(' '); + + if (is_neg) + OUTCHAR('-'); + else if (p->flags & FLAGS_SHOWSIGN) + OUTCHAR('+'); + else if (p->flags & FLAGS_SPACE) + OUTCHAR(' '); + + if (alt && base == 16) { + OUTCHAR('0'); + if(p->flags & FLAGS_UPPER) + OUTCHAR('X'); + else + OUTCHAR('x'); + } + + if (!(p->flags & FLAGS_LEFT) && (p->flags & FLAGS_PAD_NIL)) + while (width-- > 0) + OUTCHAR('0'); + + /* Write the number. */ + while (++w <= workend) { + OUTCHAR(*w); + } + + if (p->flags & FLAGS_LEFT) + while (width-- > 0) + OUTCHAR(' '); } break; case FORMAT_STRING: - /* String. */ + /* String. */ { - static char null[] = "(nil)"; - char *str; - size_t len; - - str = (char *) p->data.str; - if ( str == NULL) { - /* Write null[] if there's space. */ - if (prec == -1 || prec >= (long) sizeof(null) - 1) { - str = null; - len = sizeof(null) - 1; - /* Disable quotes around (nil) */ - p->flags &= (~FLAGS_ALT); - } - else { - str = (char *)""; - len = 0; - } - } - else - len = strlen(str); - - if (prec != -1 && (size_t) prec < len) - len = prec; - width -= len; - - if (p->flags & FLAGS_ALT) - OUTCHAR('"'); - - if (!(p->flags&FLAGS_LEFT)) - while (width-- > 0) - OUTCHAR(' '); - - while (len-- > 0) - OUTCHAR(*str++); - if (p->flags&FLAGS_LEFT) - while (width-- > 0) - OUTCHAR(' '); - - if (p->flags & FLAGS_ALT) - OUTCHAR('"'); + static char null[] = "(nil)"; + char *str; + size_t len; + + str = (char *) p->data.str; + if ( str == NULL) { + /* Write null[] if there's space. */ + if (prec == -1 || prec >= (long) sizeof(null) - 1) { + str = null; + len = sizeof(null) - 1; + /* Disable quotes around (nil) */ + p->flags &= (~FLAGS_ALT); + } + else { + str = (char *)""; + len = 0; + } + } + else + len = strlen(str); + + if (prec != -1 && (size_t) prec < len) + len = prec; + width -= len; + + if (p->flags & FLAGS_ALT) + OUTCHAR('"'); + + if (!(p->flags&FLAGS_LEFT)) + while (width-- > 0) + OUTCHAR(' '); + + while (len-- > 0) + OUTCHAR(*str++); + if (p->flags&FLAGS_LEFT) + while (width-- > 0) + OUTCHAR(' '); + + if (p->flags & FLAGS_ALT) + OUTCHAR('"'); } break; case FORMAT_PTR: /* Generic pointer. */ { - void *ptr; - ptr = (void *) p->data.ptr; - if (ptr != NULL) { - /* If the pointer is not NULL, write it as a %#x spec. */ - base = 16; - digits = (p->flags & FLAGS_UPPER)? upper_digits : lower_digits; - alt = 1; - num = (unsigned long) ptr; - is_neg = 0; - goto number; - } - else { - /* Write "(nil)" for a nil pointer. */ - static char strnil[] = "(nil)"; - char *point; - - width -= sizeof(strnil) - 1; - if (p->flags & FLAGS_LEFT) - while (width-- > 0) - OUTCHAR(' '); - for (point = strnil; *point != '\0'; ++point) - OUTCHAR(*point); - if (! (p->flags & FLAGS_LEFT)) - while (width-- > 0) - OUTCHAR(' '); - } + void *ptr; + ptr = (void *) p->data.ptr; + if (ptr != NULL) { + /* If the pointer is not NULL, write it as a %#x spec. */ + base = 16; + digits = (p->flags & FLAGS_UPPER)? upper_digits : lower_digits; + alt = 1; + num = (unsigned long) ptr; + is_neg = 0; + goto number; + } + else { + /* Write "(nil)" for a nil pointer. */ + static char strnil[] = "(nil)"; + char *point; + + width -= sizeof(strnil) - 1; + if (p->flags & FLAGS_LEFT) + while (width-- > 0) + OUTCHAR(' '); + for (point = strnil; *point != '\0'; ++point) + OUTCHAR(*point); + if (! (p->flags & FLAGS_LEFT)) + while (width-- > 0) + OUTCHAR(' '); + } } break; case FORMAT_DOUBLE: { - char formatbuf[32]="%"; - char *fptr; - - width = -1; - if (p->flags & FLAGS_WIDTH) - width = p->width; - else if (p->flags & FLAGS_WIDTHPARAM) - width = vto[p->width].data.num; - - prec = -1; - if (p->flags & FLAGS_PREC) - prec = p->precision; - else if (p->flags & FLAGS_PRECPARAM) - prec = vto[p->precision].data.num; - - if (p->flags & FLAGS_LEFT) - strcat(formatbuf, "-"); - if (p->flags & FLAGS_SHOWSIGN) - strcat(formatbuf, "+"); - if (p->flags & FLAGS_SPACE) - strcat(formatbuf, " "); - if (p->flags & FLAGS_ALT) - strcat(formatbuf, "#"); - - fptr=&formatbuf[strlen(formatbuf)]; - - if(width >= 0) { - /* RECURSIVE USAGE */ - fptr += curl_msprintf(fptr, "%ld", width); - } - if(prec >= 0) { - /* RECURSIVE USAGE */ - fptr += curl_msprintf(fptr, ".%ld", prec); - } - if (p->flags & FLAGS_LONG) - strcat(fptr, "l"); - - if (p->flags & FLAGS_FLOATE) - strcat(fptr, p->flags&FLAGS_UPPER?"E":"e"); - else if (p->flags & FLAGS_FLOATG) - strcat(fptr, (p->flags & FLAGS_UPPER) ? "G" : "g"); - else - strcat(fptr, "f"); - - /* NOTE NOTE NOTE!! Not all sprintf() implementations returns number - of output characters */ + char formatbuf[32]="%"; + char *fptr; + size_t left = sizeof(formatbuf)-strlen(formatbuf); + int len; + + width = -1; + if (p->flags & FLAGS_WIDTH) + width = p->width; + else if (p->flags & FLAGS_WIDTHPARAM) + width = vto[p->width].data.num; + + prec = -1; + if (p->flags & FLAGS_PREC) + prec = p->precision; + else if (p->flags & FLAGS_PRECPARAM) + prec = vto[p->precision].data.num; + + if (p->flags & FLAGS_LEFT) + strcat(formatbuf, "-"); + if (p->flags & FLAGS_SHOWSIGN) + strcat(formatbuf, "+"); + if (p->flags & FLAGS_SPACE) + strcat(formatbuf, " "); + if (p->flags & FLAGS_ALT) + strcat(formatbuf, "#"); + + fptr=&formatbuf[strlen(formatbuf)]; + + if(width >= 0) { + /* RECURSIVE USAGE */ + len = curl_msnprintf(fptr, left, "%ld", width); + fptr += len; + left -= len; + } + if(prec >= 0) { + /* RECURSIVE USAGE */ + len = curl_msnprintf(fptr, left, ".%ld", prec); + fptr += len; + left -= len; + } + if (p->flags & FLAGS_LONG) + *fptr++ = 'l'; + + if (p->flags & FLAGS_FLOATE) + *fptr++ = p->flags&FLAGS_UPPER ? 'E':'e'; + else if (p->flags & FLAGS_FLOATG) + *fptr++ = p->flags & FLAGS_UPPER ? 'G' : 'g'; + else + *fptr++ = 'f'; + + *fptr = 0; /* and a final zero termination */ + + /* NOTE NOTE NOTE!! Not all sprintf() implementations returns number + of output characters */ (sprintf)(work, formatbuf, p->data.dnum); - for(fptr=work; *fptr; fptr++) - OUTCHAR(*fptr); + for(fptr=work; *fptr; fptr++) + OUTCHAR(*fptr); } break; @@ -951,15 +958,15 @@ static int dprintf_formatf( /* Answer the count of characters written. */ #ifdef ENABLE_64BIT if (p->flags & FLAGS_LONGLONG) - *(LONG_LONG *) p->data.ptr = (LONG_LONG)done; + *(LONG_LONG *) p->data.ptr = (LONG_LONG)done; else #endif - if (p->flags & FLAGS_LONG) - *(long *) p->data.ptr = (long)done; + if (p->flags & FLAGS_LONG) + *(long *) p->data.ptr = (long)done; else if (!(p->flags & FLAGS_SHORT)) - *(int *) p->data.ptr = (int)done; + *(int *) p->data.ptr = (int)done; else - *(short *) p->data.ptr = (short)done; + *(short *) p->data.ptr = (short)done; break; default: diff --git a/lib/progress.c b/lib/progress.c index a36def75c..27cde9c38 100644 --- a/lib/progress.c +++ b/lib/progress.c @@ -51,20 +51,21 @@ static void time2str(char *r, long t) if(h <= 99) { long m = (t-(h*3600))/60; long s = (t-(h*3600)-(m*60)); - sprintf(r, "%2ld:%02ld:%02ld",h,m,s); + snprintf(r, 9, "%2ld:%02ld:%02ld",h,m,s); } else { /* this equals to more than 99 hours, switch to a more suitable output format to fit within the limits. */ if(h/24 <= 999) - sprintf(r, "%3ldd %02ldh", h/24, h-(h/24)*24); + snprintf(r, 9, "%3ldd %02ldh", h/24, h-(h/24)*24); else - sprintf(r, "%7ldd", h/24); + snprintf(r, 9, "%7ldd", h/24); } } /* The point of this function would be to return a string of the input data, - but never longer than 5 columns. Add suffix k, M, G when suitable... */ + but never longer than 5 columns (+ one zero byte). + Add suffix k, M, G when suitable... */ static char *max5data(curl_off_t bytes, char *max5) { #define ONE_KILOBYTE 1024 @@ -74,38 +75,38 @@ static char *max5data(curl_off_t bytes, char *max5) #define ONE_PETABYTE ((curl_off_t)1024* ONE_TERRABYTE) if(bytes < 100000) { - sprintf(max5, "%5" FORMAT_OFF_T, bytes); + snprintf(max5, 6, "%5" FORMAT_OFF_T, bytes); } else if(bytes < (10000*ONE_KILOBYTE)) { - sprintf(max5, "%4" FORMAT_OFF_T "k", (curl_off_t)(bytes/ONE_KILOBYTE)); + snprintf(max5, 6, "%4" FORMAT_OFF_T "k", (curl_off_t)(bytes/ONE_KILOBYTE)); } else if(bytes < (100*ONE_MEGABYTE)) { /* 'XX.XM' is good as long as we're less than 100 megs */ - sprintf(max5, "%2d.%0dM", - (int)(bytes/ONE_MEGABYTE), - (int)(bytes%ONE_MEGABYTE)/(ONE_MEGABYTE/10) ); + snprintf(max5, 6, "%2d.%0dM", + (int)(bytes/ONE_MEGABYTE), + (int)(bytes%ONE_MEGABYTE)/(ONE_MEGABYTE/10) ); } #if SIZEOF_CURL_OFF_T > 4 else if(bytes < ( (curl_off_t)10000*ONE_MEGABYTE)) /* 'XXXXM' is good until we're at 10000MB or above */ - sprintf(max5, "%4" FORMAT_OFF_T "M", (curl_off_t)(bytes/ONE_MEGABYTE)); + snprintf(max5, 6, "%4" FORMAT_OFF_T "M", (curl_off_t)(bytes/ONE_MEGABYTE)); else if(bytes < (curl_off_t)100*ONE_GIGABYTE) /* 10000 MB - 100 GB, we show it as XX.XG */ - sprintf(max5, "%2d.%0dG", - (int)(bytes/ONE_GIGABYTE), - (int)(bytes%ONE_GIGABYTE)/(ONE_GIGABYTE/10) ); + snprintf(max5, 6, "%2d.%0dG", + (int)(bytes/ONE_GIGABYTE), + (int)(bytes%ONE_GIGABYTE)/(ONE_GIGABYTE/10) ); else if(bytes < (curl_off_t)10000 * ONE_GIGABYTE) /* up to 10000GB, display without decimal: XXXXG */ - sprintf(max5, "%4dG", (int)(bytes/ONE_GIGABYTE)); + snprintf(max5, 6, "%4dG", (int)(bytes/ONE_GIGABYTE)); else if(bytes < (curl_off_t)10000 * ONE_TERRABYTE) /* up to 10000TB, display without decimal: XXXXT */ - sprintf(max5, "%4dT", (int)(bytes/ONE_TERRABYTE)); + snprintf(max5, 6, "%4dT", (int)(bytes/ONE_TERRABYTE)); else { /* up to 10000PB, display without decimal: XXXXP */ - sprintf(max5, "%4dP", (int)(bytes/ONE_PETABYTE)); + snprintf(max5, 6, "%4dP", (int)(bytes/ONE_PETABYTE)); /* 16384 petabytes (16 exabytes) is maximum a 64 bit number can hold, but this type is signed so 8192PB will be max.*/ @@ -113,7 +114,7 @@ static char *max5data(curl_off_t bytes, char *max5) #else else - sprintf(max5, "%4" FORMAT_OFF_T "M", (curl_off_t)(bytes/ONE_MEGABYTE)); + snprintf(max5, 6, "%4" FORMAT_OFF_T "M", (curl_off_t)(bytes/ONE_MEGABYTE)); #endif return max5; diff --git a/lib/ssluse.c b/lib/ssluse.c index 6404f7ac0..aa7da18e3 100644 --- a/lib/ssluse.c +++ b/lib/ssluse.c @@ -1056,8 +1056,8 @@ static void ssl_tls_trace(int direction, int ssl_ver, int content_type, msg_type = *(char*)buf; msg_name = ssl_msg_type(ssl_ver, msg_type); - txt_len = 1 + sprintf(ssl_buf, "SSLv%c, %s%s (%d):\n", - ver, tls_rt_name, msg_name, msg_type); + txt_len = 1 + snprintf(ssl_buf, sizeof(ssl_buf), "SSLv%c, %s%s (%d):\n", + ver, tls_rt_name, msg_name, msg_type); Curl_debug(data, CURLINFO_TEXT, ssl_buf, txt_len, NULL); Curl_debug(data, (direction == 1) ? CURLINFO_SSL_DATA_OUT : diff --git a/lib/version.c b/lib/version.c index 7bd4dbe50..21939d925 100644 --- a/lib/version.c +++ b/lib/version.c @@ -1,8 +1,8 @@ /*************************************************************************** - * _ _ ____ _ - * Project ___| | | | _ \| | - * / __| | | | |_) | | - * | (__| |_| | _ <| |___ + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * * Copyright (C) 1998 - 2004, Daniel Stenberg, , et al. @@ -10,7 +10,7 @@ * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms * are also available at http://curl.haxx.se/docs/copyright.html. - * + * * You may opt to use, copy, modify, merge, publish, distribute and/or sell * copies of the Software, and permit persons to whom the Software is * furnished to do so, under the terms of the COPYING file. @@ -29,6 +29,9 @@ #include #include "urldata.h" +#define _MPRINTF_REPLACE /* use the internal *printf() functions */ +#include + #ifdef USE_ARES #include #endif @@ -38,7 +41,7 @@ #endif #ifdef USE_SSLEAY -static void getssl_version(char *ptr, long *num) +static int getssl_version(char *ptr, size_t left, long *num) { #if (SSLEAY_VERSION_NUMBER >= 0x905000) @@ -60,20 +63,20 @@ static void getssl_version(char *ptr, long *num) sub[0]='\0'; } - sprintf(ptr, " OpenSSL/%lx.%lx.%lx%s", - (ssleay_value>>28)&0xf, - (ssleay_value>>20)&0xff, - (ssleay_value>>12)&0xff, - sub); + return snprintf(ptr, left, " OpenSSL/%lx.%lx.%lx%s", + (ssleay_value>>28)&0xf, + (ssleay_value>>20)&0xff, + (ssleay_value>>12)&0xff, + sub); } #else *num = SSLEAY_VERSION_NUMBER; #if (SSLEAY_VERSION_NUMBER >= 0x900000) - sprintf(ptr, " OpenSSL/%lx.%lx.%lx", - (SSLEAY_VERSION_NUMBER>>28)&0xff, - (SSLEAY_VERSION_NUMBER>>20)&0xff, - (SSLEAY_VERSION_NUMBER>>12)&0xf); + return snprintf(ptr, left, " OpenSSL/%lx.%lx.%lx", + (SSLEAY_VERSION_NUMBER>>28)&0xff, + (SSLEAY_VERSION_NUMBER>>20)&0xff, + (SSLEAY_VERSION_NUMBER>>12)&0xf); #else { char sub[2]; @@ -84,10 +87,10 @@ static void getssl_version(char *ptr, long *num) else sub[0]='\0'; - sprintf(ptr, " SSL/%x.%x.%x%s", - (SSLEAY_VERSION_NUMBER>>12)&0xff, - (SSLEAY_VERSION_NUMBER>>8)&0xf, - (SSLEAY_VERSION_NUMBER>>4)&0xf, sub); + return snprintf(ptr, left, " SSL/%x.%x.%x%s", + (SSLEAY_VERSION_NUMBER>>12)&0xff, + (SSLEAY_VERSION_NUMBER>>8)&0xf, + (SSLEAY_VERSION_NUMBER>>4)&0xf, sub); } #endif #endif @@ -99,42 +102,37 @@ char *curl_version(void) { static char version[200]; char *ptr=version; + int len; + size_t left = sizeof(version); strcpy(ptr, LIBCURL_NAME "/" LIBCURL_VERSION ); ptr=strchr(ptr, '\0'); + left -= strlen(ptr); #ifdef USE_SSLEAY { long num; - getssl_version(ptr, &num); - ptr=strchr(version, '\0'); + len = getssl_version(ptr, left, &num); + left -= len; + ptr += len; } #endif -#ifdef HAVE_KRB4 - sprintf(ptr, " krb4"); - ptr += strlen(ptr); -#endif -#ifdef ENABLE_IPV6 - sprintf(ptr, " ipv6"); - ptr += strlen(ptr); -#endif #ifdef HAVE_LIBZ - sprintf(ptr, " zlib/%s", zlibVersion()); - ptr += strlen(ptr); -#endif -#ifdef HAVE_GSSAPI - sprintf(ptr, " GSS"); - ptr += strlen(ptr); + len = snprintf(ptr, left, " zlib/%s", zlibVersion()); + left -= len; + ptr += len; #endif #ifdef USE_ARES /* this function is only present in c-ares, not in the original ares */ - sprintf(ptr, " c-ares/%s", ares_version(NULL)); - ptr += strlen(ptr); + len = snprintf(ptr, left, " c-ares/%s", ares_version(NULL)); + left -= len; + ptr += len; #endif #ifdef USE_LIBIDN if(stringprep_check_version(LIBIDN_REQUIRED_VERSION)) { - sprintf(ptr, " libidn/%s", stringprep_check_version(NULL)); - ptr += strlen(ptr); + len = snprintf(ptr, left, " libidn/%s", stringprep_check_version(NULL)); + left -= len; + ptr += len; } #endif @@ -226,7 +224,7 @@ curl_version_info_data *curl_version_info(CURLversion stamp) #ifdef USE_SSLEAY static char ssl_buffer[80]; long num; - getssl_version(ssl_buffer, &num); + getssl_version(ssl_buffer, sizeof(ssl_buffer), &num); version_info.ssl_version = ssl_buffer; version_info.ssl_version_num = num; -- cgit v1.2.3