curlx: curlx_strcopy() instead of strcpy()
No binary (build failed)
—
(log yok)
| @@ -31,6 +31,7 @@ LIB_CURLX_CFILES = \ | |
| curlx/inet_pton.c \ | |
| curlx/multibyte.c \ | |
| curlx/nonblock.c \ | |
| + | curlx/strcopy.c \ |
| curlx/strerr.c \ | |
| curlx/strparse.c \ | |
| curlx/timediff.c \ | |
| @@ -51,6 +52,7 @@ LIB_CURLX_HFILES = \ | |
| curlx/multibyte.h \ | |
| curlx/nonblock.h \ | |
| curlx/snprintf.h \ | |
| + | curlx/strcopy.h \ |
| curlx/strerr.h \ | |
| curlx/strparse.h \ | |
| curlx/timediff.h \ | |
| @@ -23,8 +23,8 @@ | |
| ***************************************************************************/ | |
| #include "curl_setup.h" | |
| - | |
| #include "curl_gethostname.h" | |
| + | #include "curlx/strcopy.h" |
| /* | |
| * Curl_gethostname() is a wrapper around gethostname() which allows | |
| @@ -60,7 +60,7 @@ int Curl_gethostname(char * const name, GETHOSTNAME_TYPE_ARG2 namelen) | |
| const char *force_hostname = getenv("CURL_GETHOSTNAME"); | |
| if(force_hostname) { | |
| if(strlen(force_hostname) < (size_t)namelen) | |
| - | strcpy(name, force_hostname); |
| + | curlx_strcopy(name, namelen, force_hostname, strlen(force_hostname)); |
| else | |
| return 1; /* cannot do it */ | |
| err = 0; | |
| @@ -28,6 +28,7 @@ | |
| #include "curl_gssapi.h" | |
| #include "curl_trc.h" | |
| + | #include "curlx/strcopy.h" |
| #ifdef DEBUGBUILD | |
| #if defined(HAVE_GSSGNU) || !defined(_WIN32) | |
| @@ -224,7 +225,7 @@ stub_gss_init_sec_context(OM_uint32 *min, | |
| return GSS_S_FAILURE; | |
| } | |
| - | strcpy(ctx->creds, creds); |
| + | curlx_strcopy(ctx->creds, sizeof(ctx->creds), creds, strlen(creds)); |
| ctx->flags = req_flags; | |
| } | |
| @@ -43,6 +43,7 @@ | |
| #include "curlx/strparse.h" | |
| #include "vtls/vtls.h" | |
| #include "vquic/vquic.h" | |
| + | #include "curlx/strcopy.h" |
| static void trc_write(struct Curl_easy *data, curl_infotype type, | |
| const char *ptr, size_t size) | |
| @@ -184,7 +185,7 @@ void Curl_failf(struct Curl_easy *data, const char *fmt, ...) | |
| len = curl_mvsnprintf(error, CURL_ERROR_SIZE, fmt, ap); | |
| if(data->set.errorbuffer && !data->state.errorbuf) { | |
| - | strcpy(data->set.errorbuffer, error); |
| + | curlx_strcopy(data->set.errorbuffer, CURL_ERROR_SIZE, error, len); |
| data->state.errorbuf = TRUE; /* wrote error string */ | |
| } | |
| error[len++] = '\n'; | |
| @@ -55,6 +55,9 @@ | |
| #include "strparse.h" | |
| /* The curlx_str_* parsing functions */ | |
| + | #include "strcopy.h" |
| + | /* curlx_strcopy */ |
| + | |
| #include "dynbuf.h" | |
| /* The curlx_dyn_* functions */ | |
| @@ -33,6 +33,7 @@ | |
| #include "inet_ntop.h" | |
| #include "snprintf.h" | |
| + | #include "strcopy.h" |
| #define IN6ADDRSZ 16 | |
| /* #define INADDRSZ 4 */ | |
| @@ -78,7 +79,7 @@ static char *inet_ntop4(const unsigned char *src, char *dst, size_t size) | |
| #endif | |
| return NULL; | |
| } | |
| - | strcpy(dst, tmp); |
| + | curlx_strcopy(dst, size, tmp, len); |
| return dst; | |
| } | |
| @@ -183,8 +184,7 @@ static char *inet_ntop6(const unsigned char *src, char *dst, size_t size) | |
| *tp++ = ':'; | |
| *tp++ = '\0'; | |
| - | /* Check for overflow, copy, and we are done. |
| - | */ |
| + | /* Check for overflow, copy, and we are done. */ |
| if((size_t)(tp - tmp) > size) { | |
| #ifdef USE_WINSOCK | |
| errno = WSAEINVAL; | |
| @@ -193,7 +193,8 @@ static char *inet_ntop6(const unsigned char *src, char *dst, size_t size) | |
| #endif | |
| return NULL; | |
| } | |
| - | strcpy(dst, tmp); |
| + | |
| + | curlx_strcopy(dst, size, tmp, strlen(tmp)); |
| return dst; | |
| } | |
| @@ -0,0 +1,49 @@ | |
| + | /*************************************************************************** |
| + | * _ _ ____ _ |
| + | * Project ___| | | | _ \| | |
| + | * / __| | | | |_) | | |
| + | * | (__| |_| | _ <| |___ |
| + | * \___|\___/|_| \_\_____| |
| + | * |
| + | * Copyright (C) Daniel Stenberg, <[email protected]>, et al. |
| + | * |
| + | * 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 https://curl.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. |
| + | * |
| + | * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY |
| + | * KIND, either express or implied. |
| + | * |
| + | * SPDX-License-Identifier: curl |
| + | * |
| + | ***************************************************************************/ |
| + | #include "../curl_setup.h" |
| + | #include "strcopy.h" |
| + | |
| + | /* |
| + | * curlx_strcopy() is a replacement for strcpy(). |
| + | * |
| + | * Provide the target buffer @dest and size of the target buffer @dsize, If |
| + | * the source string @src with its *string length* @slen fits in the target |
| + | * buffer it will be copied there - including storing a null terminator. |
| + | * |
| + | * If the target buffer is too small, the copy is not performed but if the |
| + | * target buffer has a non-zero size it will get a null terminator stored. |
| + | */ |
| + | void curlx_strcopy(char *dest, /* destination buffer */ |
| + | size_t dsize, /* size of target buffer */ |
| + | const char *src, /* source string */ |
| + | size_t slen) /* length of source string to copy */ |
| + | { |
| + | DEBUGASSERT(slen < dsize); |
| + | if(slen < dsize) { |
| + | memcpy(dest, src, slen); |
| + | dest[slen] = 0; |
| + | } |
| + | else if(dsize) |
| + | dest[0] = 0; |
| + | } |
| @@ -0,0 +1,32 @@ | |
| + | #ifndef HEADER_CURLX_STRCOPY_H |
| + | #define HEADER_CURLX_STRCOPY_H |
| + | /*************************************************************************** |
| + | * _ _ ____ _ |
| + | * Project ___| | | | _ \| | |
| + | * / __| | | | |_) | | |
| + | * | (__| |_| | _ <| |___ |
| + | * \___|\___/|_| \_\_____| |
| + | * |
| + | * Copyright (C) Daniel Stenberg, <[email protected]>, et al. |
| + | * |
| + | * 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 https://curl.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. |
| + | * |
| + | * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY |
| + | * KIND, either express or implied. |
| + | * |
| + | * SPDX-License-Identifier: curl |
| + | * |
| + | ***************************************************************************/ |
| + | |
| + | void curlx_strcopy(char *dest, |
| + | size_t dsize, /* size of target buffer */ |
| + | const char *src, |
| + | size_t slen); /* length of string to copy */ |
| + | |
| + | #endif /* HEADER_CURLX_STRCOPY_H */ |
| @@ -35,6 +35,7 @@ | |
| #include "winapi.h" | |
| #include "snprintf.h" | |
| #include "strerr.h" | |
| + | #include "strcopy.h" |
| #ifdef USE_WINSOCK | |
| /* This is a helper function for curlx_strerror that converts Winsock error | |
| @@ -224,8 +225,7 @@ static const char *get_winsock_error(int err, char *buf, size_t len) | |
| return NULL; | |
| } | |
| alen = strlen(p); | |
| - | if(alen < len) |
| - | strcpy(buf, p); |
| + | curlx_strcopy(buf, len, p, alen); |
| return buf; | |
| #endif | |
| } | |
| @@ -30,6 +30,7 @@ | |
| #ifdef _WIN32 | |
| #include "winapi.h" | |
| #include "snprintf.h" | |
| + | #include "strcopy.h" |
| /* This is a helper function for curlx_strerror that converts Windows API error | |
| * codes (GetLastError) to error messages. | |
| @@ -93,8 +94,7 @@ const char *curlx_winapi_strerror(DWORD err, char *buf, size_t buflen) | |
| #else | |
| { | |
| const char *txt = (err == ERROR_SUCCESS) ? "No error" : "Error"; | |
| - | if(strlen(txt) < buflen) |
| - | strcpy(buf, txt); |
| + | curlx_strcopy(buf, buflen, txt, strlen(txt)); |
| } | |
| #endif | |
| @@ -60,6 +60,7 @@ | |
| #include "select.h" | |
| #include "strcase.h" | |
| #include "easy_lock.h" | |
| + | #include "curlx/strcopy.h" |
| #include "curlx/strparse.h" | |
| #if defined(CURLRES_SYNCH) && \ | |
| @@ -622,7 +623,7 @@ static struct Curl_addrinfo *get_localhost6(int port, const char *name) | |
| ca->ai_addr = (void *)((char *)ca + sizeof(struct Curl_addrinfo)); | |
| memcpy(ca->ai_addr, &sa6, ss_size); | |
| ca->ai_canonname = (char *)ca->ai_addr + ss_size; | |
| - | strcpy(ca->ai_canonname, name); |
| + | curlx_strcopy(ca->ai_canonname, hostlen + 1, name, hostlen); |
| return ca; | |
| } | |
| #else | |
| @@ -659,7 +660,7 @@ static struct Curl_addrinfo *get_localhost(int port, const char *name) | |
| ca->ai_addr = (void *)((char *)ca + sizeof(struct Curl_addrinfo)); | |
| memcpy(ca->ai_addr, &sa, ss_size); | |
| ca->ai_canonname = (char *)ca->ai_addr + ss_size; | |
| - | strcpy(ca->ai_canonname, name); |
| + | curlx_strcopy(ca->ai_canonname, hostlen + 1, name, hostlen); |
| ca6 = get_localhost6(port, name); | |
| if(!ca6) | |
| @@ -37,6 +37,7 @@ | |
| #include "curl_share.h" | |
| #include "curlx/strparse.h" | |
| #include "curlx/timeval.h" | |
| + | #include "curlx/strcopy.h" |
| #define MAX_HSTS_LINE 4095 | |
| #define MAX_HSTS_HOSTLEN 2048 | |
| @@ -294,7 +295,7 @@ static CURLcode hsts_push(struct Curl_easy *data, | |
| stamp.tm_hour, stamp.tm_min, stamp.tm_sec); | |
| } | |
| else | |
| - | strcpy(e.expire, UNLIMITED); |
| + | curlx_strcopy(e.expire, sizeof(e.expire), UNLIMITED, strlen(UNLIMITED)); |
| sc = data->set.hsts_write(data, &e, i, data->set.hsts_write_userp); | |
| *stop = (sc != CURLSTS_OK); | |
| @@ -73,7 +73,7 @@ | |
| #include "url.h" | |
| #include "bufref.h" | |
| #include "curl_sasl.h" | |
| - | |
| + | #include "curlx/strcopy.h" |
| /* meta key for storing protocol meta at easy handle */ | |
| #define CURL_META_IMAP_EASY "meta:proto:imap:easy" | |
| @@ -1679,7 +1679,7 @@ static CURLcode imap_connect(struct Curl_easy *data, bool *done) | |
| imap_state(data, imapc, IMAP_SERVERGREET); | |
| /* Start off with an response id of '*' */ | |
| - | strcpy(imapc->resptag, "*"); |
| + | curlx_strcopy(imapc->resptag, sizeof(imapc->resptag), "*", 1); |
| result = imap_multi_statemach(data, done); | |
| @@ -32,6 +32,7 @@ struct Curl_easy; | |
| #include "curl_trc.h" | |
| #include "transfer.h" | |
| #include "strdup.h" | |
| + | #include "curlx/strcopy.h" |
| #include "curlx/fopen.h" | |
| #include "curlx/base64.h" | |
| @@ -602,7 +603,7 @@ static size_t encoder_qp_read(char *buffer, size_t size, bool ateof, | |
| } | |
| } | |
| if(softlinebreak) { | |
| - | strcpy(buf, "\x3D\x0D\x0A"); /* "=\r\n" */ |
| + | curlx_strcopy(buf, sizeof(buf), "\x3D\x0D\x0A", 3); /* "=\r\n" */ |
| len = 3; | |
| consumed = 0; | |
| } | |
| @@ -30,6 +30,7 @@ | |
| #include "progress.h" | |
| #include "transfer.h" | |
| #include "curlx/timeval.h" | |
| + | #include "curlx/strcopy.h" |
| /* check rate limits within this many recent milliseconds, at minimum. */ | |
| #define MIN_RATE_LIMIT_PERIOD 3000 | |
| @@ -37,18 +38,18 @@ | |
| #ifndef CURL_DISABLE_PROGRESS_METER | |
| /* Provide a string that is 2 + 1 + 2 + 1 + 2 = 8 letters long (plus the zero | |
| byte) */ | |
| - | static void time2str(char *r, curl_off_t seconds) |
| + | static void time2str(char *r, size_t rsize, curl_off_t seconds) |
| { | |
| curl_off_t h; | |
| if(seconds <= 0) { | |
| - | strcpy(r, "--:--:--"); |
| + | curlx_strcopy(r, rsize, "--:--:--", 8); |
| return; | |
| } | |
| h = seconds / 3600; | |
| if(h <= 99) { | |
| curl_off_t m = (seconds - (h * 3600)) / 60; | |
| curl_off_t s = (seconds - (h * 3600)) - (m * 60); | |
| - | curl_msnprintf(r, 9, "%2" FMT_OFF_T ":%02" FMT_OFF_T ":%02" FMT_OFF_T, |
| + | curl_msnprintf(r, rsize, "%2" FMT_OFF_T ":%02" FMT_OFF_T ":%02" FMT_OFF_T, |
| h, m, s); | |
| } | |
| else { | |
| @@ -57,21 +58,21 @@ static void time2str(char *r, curl_off_t seconds) | |
| curl_off_t d = seconds / 86400; | |
| h = (seconds - (d * 86400)) / 3600; | |
| if(d <= 999) | |
| - | curl_msnprintf(r, 9, "%3" FMT_OFF_T "d %02" FMT_OFF_T "h", d, h); |
| + | curl_msnprintf(r, rsize, "%3" FMT_OFF_T "d %02" FMT_OFF_T "h", d, h); |
| else | |
| - | curl_msnprintf(r, 9, "%7" FMT_OFF_T "d", d); |
| + | curl_msnprintf(r, rsize, "%7" FMT_OFF_T "d", d); |
| } | |
| } | |
| /* The point of this function would be to return a string of the input data, | |
| but never longer than 6 columns (+ one zero byte). | |
| Add suffix k, M, G when suitable... */ | |
| - | static char *max6data(curl_off_t bytes, char *max6) |
| + | static char *max6out(curl_off_t bytes, char *max6, size_t mlen) |
| { | |
| /* a signed 64-bit value is 8192 petabytes maximum, shown as | |
| 8.0E (exabytes)*/ | |
| if(bytes < 100000) | |
| - | curl_msnprintf(max6, 7, "%6" CURL_FORMAT_CURL_OFF_T, bytes); |
| + | curl_msnprintf(max6, mlen, "%6" CURL_FORMAT_CURL_OFF_T, bytes); |
| else { | |
| const char unit[] = { 'k', 'M', 'G', 'T', 'P', 'E', 0 }; | |
| int k = 0; | |
| @@ -85,7 +86,7 @@ static char *max6data(curl_off_t bytes, char *max6) | |
| DEBUGASSERT(unit[k]); | |
| } while(unit[k]); | |
| /* xxx.yU */ | |
| - | curl_msnprintf(max6, 7, "%3" CURL_FORMAT_CURL_OFF_T |
| + | curl_msnprintf(max6, mlen, "%3" CURL_FORMAT_CURL_OFF_T |
| ".%" CURL_FORMAT_CURL_OFF_T "%c", nbytes, | |
| (bytes % 1024) / (1024 / 10), unit[k]); | |
| } | |
| @@ -528,9 +529,10 @@ static void progress_meter(struct Curl_easy *data) | |
| /* Since both happen at the same time, total expected duration is max. */ | |
| total_estm.secs = CURLMAX(ul_estm.secs, dl_estm.secs); | |
| /* create the three time strings */ | |
| - | time2str(time_left, total_estm.secs > 0 ? (total_estm.secs - cur_secs) : 0); |
| - | time2str(time_total, total_estm.secs); |
| - | time2str(time_spent, cur_secs); |
| + | time2str(time_left, sizeof(time_left), |
| + | total_estm.secs > 0 ? (total_estm.secs - cur_secs) : 0); |
| + | time2str(time_total, sizeof(time_total), total_estm.secs); |
| + | time2str(time_spent, sizeof(time_spent), cur_secs); |
| /* Get the total amount of data expected to get transferred */ | |
| total_expected_size = p->ul_size_known ? p->ul.total_size : p->ul.cur_size; | |
| @@ -554,18 +556,24 @@ static void progress_meter(struct Curl_easy *data) | |
| "%3" FMT_OFF_T " %s " | |
| "%3" FMT_OFF_T " %s " | |
| "%3" FMT_OFF_T " %s %s %s %s %s %s %s", | |
| - | total_estm.percent, /* 3 letters */ /* total % */ |
| - | max6data(total_expected_size, max6[2]), /* total size */ |
| - | dl_estm.percent, /* 3 letters */ /* rcvd % */ |
| - | max6data(p->dl.cur_size, max6[0]), /* rcvd size */ |
| - | ul_estm.percent, /* 3 letters */ /* xfer % */ |
| - | max6data(p->ul.cur_size, max6[1]), /* xfer size */ |
| - | max6data(p->dl.speed, max6[3]), /* avrg dl speed */ |
| - | max6data(p->ul.speed, max6[4]), /* avrg ul speed */ |
| - | time_total, /* 8 letters */ /* total time */ |
| - | time_spent, /* 8 letters */ /* time spent */ |
| - | time_left, /* 8 letters */ /* time left */ |
| - | max6data(p->current_speed, max6[5]) |
| + | total_estm.percent, /* 3 letters */ /* total % */ |
| + | max6out(total_expected_size, max6[2], |
| + | sizeof(max6[2])), /* total size */ |
| + | dl_estm.percent, /* 3 letters */ /* rcvd % */ |
| + | max6out(p->dl.cur_size, max6[0], |
| + | sizeof(max6[0])), /* rcvd size */ |
| + | ul_estm.percent, /* 3 letters */ /* xfer % */ |
| + | max6out(p->ul.cur_size, max6[1], |
| + | sizeof(max6[1])), /* xfer size */ |
| + | max6out(p->dl.speed, max6[3], |
| + | sizeof(max6[3])), /* avrg dl speed */ |
| + | max6out(p->ul.speed, max6[4], |
| + | sizeof(max6[4])), /* avrg ul speed */ |
| + | time_total, /* 8 letters */ /* total time */ |
| + | time_spent, /* 8 letters */ /* time spent */ |
| + | time_left, /* 8 letters */ /* time left */ |
| + | max6out(p->current_speed, max6[5], |
| + | sizeof(max6[5])) /* current speed */ |
| ); | |
| /* we flush the output stream to make it appear as soon as possible */ | |
| @@ -40,7 +40,7 @@ | |
| #include "curl_ntlm_core.h" | |
| #include "escape.h" | |
| #include "curl_endian.h" | |
| - | |
| + | #include "curlx/strcopy.h" |
| /* meta key for storing protocol meta at easy handle */ | |
| #define CURL_META_SMB_EASY "meta:proto:smb:easy" | |
| @@ -790,7 +790,7 @@ static CURLcode smb_send_open(struct Curl_easy *data, | |
| msg.create_disposition = smb_swap32(SMB_FILE_OPEN); | |
| } | |
| msg.byte_count = smb_swap16((unsigned short)byte_count); | |
| - | strcpy(msg.bytes, req->path); |
| + | curlx_strcopy(msg.bytes, sizeof(msg.bytes), req->path, byte_count - 1); |
| return smb_send_message(data, smbc, req, SMB_COM_NT_CREATE_ANDX, &msg, | |
| sizeof(msg) - sizeof(msg.bytes) + byte_count); | |
| @@ -34,5 +34,4 @@ wchar_t *Curl_wcsdup(const wchar_t *src); | |
| void *Curl_memdup(const void *src, size_t buffer_length); | |
| void *Curl_saferealloc(void *ptr, size_t size); | |
| void *Curl_memdup0(const char *src, size_t length); | |
| - | |
| #endif /* HEADER_CURL_STRDUP_H */ | |
| @@ -30,6 +30,7 @@ | |
| #include "curlx/winapi.h" | |
| #include "strerror.h" | |
| + | #include "curlx/strcopy.h" |
| const char *curl_easy_strerror(CURLcode error) | |
| { | |
| @@ -663,8 +664,7 @@ const char *Curl_sspi_strerror(SECURITY_STATUS err, char *buf, size_t buflen) | |
| txt = "No error"; | |
| else | |
| txt = "Error"; | |
| - | if(buflen > strlen(txt)) |
| - | strcpy(buf, txt); |
| + | curlx_strcopy(buf, buflen, txt, strlen(txt)); |
| #endif | |
| if(errno != old_errno) | |
| @@ -62,6 +62,7 @@ | |
| #include "escape.h" | |
| #include "curlx/strerr.h" | |
| #include "curlx/strparse.h" | |
| + | #include "curlx/strcopy.h" |
| /* RFC2348 allows the block size to be negotiated */ | |
| #define TFTP_BLKSIZE_DEFAULT 512 | |
| @@ -369,12 +370,17 @@ static CURLcode tftp_parse_option_ack(struct tftp_conn *state, | |
| } | |
| static CURLcode tftp_option_add(struct tftp_conn *state, size_t *csize, | |
| - | char *buf, const char *option) |
| + | size_t index, const char *option) |
| { | |
| - | if((strlen(option) + *csize + 1) > (size_t)state->blksize) |
| + | char *buf = (char *)&state->spacket.data[index]; |
| + | size_t oplen = strlen(option); |
| + | size_t blen; |
| + | if((state->blksize <= index) || |
| + | (oplen + 1) > (size_t)(state->blksize - index)) |
| return CURLE_TFTP_ILLEGAL; | |
| - | strcpy(buf, option); |
| - | *csize += strlen(option) + 1; |
| + | blen = state->blksize - index; |
| + | curlx_strcopy(buf, blen, option, oplen); |
| + | *csize += oplen + 1; |
| return CURLE_OK; | |
| } | |
| @@ -479,32 +485,23 @@ static CURLcode tftp_send_first(struct tftp_conn *state, | |
| data->state.upload && (data->state.infilesize != -1) ? | |
| data->state.infilesize : 0); | |
| - | result = tftp_option_add(state, &sbytes, |
| - | (char *)state->spacket.data + sbytes, |
| - | TFTP_OPTION_TSIZE); |
| + | result = tftp_option_add(state, &sbytes, sbytes, TFTP_OPTION_TSIZE); |
| if(result == CURLE_OK) | |
| - | result = tftp_option_add(state, &sbytes, |
| - | (char *)state->spacket.data + sbytes, buf); |
| + | result = tftp_option_add(state, &sbytes, sbytes, buf); |
| /* add blksize option */ | |
| curl_msnprintf(buf, sizeof(buf), "%d", state->requested_blksize); | |
| if(result == CURLE_OK) | |
| - | result = tftp_option_add(state, &sbytes, |
| - | (char *)state->spacket.data + sbytes, |
| - | TFTP_OPTION_BLKSIZE); |
| + | result = tftp_option_add(state, &sbytes, sbytes, TFTP_OPTION_BLKSIZE); |
| if(result == CURLE_OK) | |
| - | result = tftp_option_add(state, &sbytes, |
| - | (char *)state->spacket.data + sbytes, buf); |
| + | result = tftp_option_add(state, &sbytes, sbytes, buf); |
| /* add timeout option */ | |
| curl_msnprintf(buf, sizeof(buf), "%d", state->retry_time); | |
| if(result == CURLE_OK) | |
| - | result = tftp_option_add(state, &sbytes, |
| - | (char *)state->spacket.data + sbytes, |
| - | TFTP_OPTION_INTERVAL); |
| + | result = tftp_option_add(state, &sbytes, sbytes, TFTP_OPTION_INTERVAL); |
| if(result == CURLE_OK) | |
| - | result = tftp_option_add(state, &sbytes, |
| - | (char *)state->spacket.data + sbytes, buf); |
| + | result = tftp_option_add(state, &sbytes, sbytes, buf); |
| if(result != CURLE_OK) { | |
| failf(data, "TFTP buffer too small for options"); | |
| @@ -509,7 +509,7 @@ static CURLUcode ipv6_parse(struct Curl_URL *u, char *hostname, | |
| hostname[hlen] = 0; /* end the address there */ | |
| if(curlx_inet_pton(AF_INET6, hostname, dest) != 1) | |
| return CURLUE_BAD_IPV6; | |
| - | if(curlx_inet_ntop(AF_INET6, dest, hostname, hlen)) { |
| + | if(curlx_inet_ntop(AF_INET6, dest, hostname, hlen + 1)) { |
| hlen = strlen(hostname); /* might be shorter now */ | |
| hostname[hlen + 1] = 0; | |
| } | |
| @@ -53,6 +53,7 @@ | |
| #include "../url.h" | |
| #include "../bufref.h" | |
| #include "../curlx/strerr.h" | |
| + | #include "../curlx/strcopy.h" |
| /* A stream window is the maximum amount we need to buffer for | |
| * each active transfer. We use HTTP/3 flow control and only ACK | |
| @@ -141,7 +142,7 @@ static char *osslq_strerror(unsigned long error, char *buf, size_t size) | |
| if(!*buf) { | |
| const char *msg = error ? "Unknown error" : "No error"; | |
| if(strlen(msg) < size) | |
| - | strcpy(buf, msg); |
| + | curlx_strcopy(buf, size, msg, strlen(msg)); |
| } | |
| return buf; | |
| @@ -61,6 +61,7 @@ | |
| #include "../multiif.h" | |
| #include "../curlx/strerr.h" | |
| #include "../curlx/strparse.h" | |
| + | #include "../curlx/strcopy.h" |
| #include "../strdup.h" | |
| #include "apple.h" | |
| @@ -773,8 +774,7 @@ static char *ossl_strerror(unsigned long error, char *buf, size_t size) | |
| if(!*buf) { | |
| const char *msg = error ? "Unknown error" : "No error"; | |
| - | if(strlen(msg) < size) |
| - | strcpy(buf, msg); |
| + | curlx_strcopy(buf, size, msg, strlen(msg)); |
| } | |
| return buf; | |
| @@ -72,6 +72,7 @@ | |
| #include "../select.h" | |
| #include "../setopt.h" | |
| #include "../strdup.h" | |
| + | #include "../curlx/strcopy.h" |
| #ifdef USE_APPLE_SECTRUST | |
| #include <Security/Security.h> | |
| @@ -1082,10 +1083,7 @@ static size_t multissl_version(char *buffer, size_t size) | |
| } | |
| if(size) { | |
| - | if(backends_len < size) |
| - | strcpy(buffer, backends); |
| - | else |
| - | *buffer = 0; /* did not fit */ |
| + | curlx_strcopy(buffer, size, backends, backends_len); |
| } | |
| return 0; | |
| } | |
| @@ -62,6 +62,7 @@ | |
| #include "../connect.h" /* for the connect timeout */ | |
| #include "../progress.h" | |
| #include "../strdup.h" | |
| + | #include "../curlx/strcopy.h" |
| #include "x509asn1.h" | |
| #include <wolfssl/ssl.h> | |
| @@ -1542,8 +1543,7 @@ static char *wssl_strerror(unsigned long error, char *buf, unsigned long size) | |
| if(!*buf) { | |
| const char *msg = error ? "Unknown error" : "No error"; | |
| - | /* the string fits because the assert above assures this */ |
| - | strcpy(buf, msg); |
| + | curlx_strcopy(buf, size, msg, strlen(msg)); |
| } | |
| return buf; | |
| @@ -40,6 +40,7 @@ | |
| #include "transfer.h" | |
| #include "select.h" | |
| #include "curlx/strparse.h" | |
| + | #include "curlx/strcopy.h" |
| /*** | |
| RFC 6455 Section 5.2 | |
| @@ -1274,7 +1275,7 @@ CURLcode Curl_ws_request(struct Curl_easy *data, struct dynbuf *req) | |
| curlx_free(randstr); | |
| return CURLE_FAILED_INIT; | |
| } | |
| - | strcpy(keyval, randstr); |
| + | curlx_strcopy(keyval, sizeof(keyval), randstr, randlen); |
| curlx_free(randstr); | |
| for(i = 0; !result && (i < CURL_ARRAYSIZE(heads)); i++) { | |
| if(!Curl_checkheaders(data, heads[i].name, strlen(heads[i].name))) { | |
| @@ -38,6 +38,7 @@ CURLX_CFILES = \ | |
| ../lib/curlx/fopen.c \ | |
| ../lib/curlx/multibyte.c \ | |
| ../lib/curlx/nonblock.c \ | |
| + | ../lib/curlx/strcopy.c \ |
| ../lib/curlx/strerr.c \ | |
| ../lib/curlx/strparse.c \ | |
| ../lib/curlx/timediff.c \ | |
| @@ -55,6 +56,7 @@ CURLX_HFILES = \ | |
| ../lib/curlx/multibyte.h \ | |
| ../lib/curlx/nonblock.h \ | |
| ../lib/curlx/snprintf.h \ | |
| + | ../lib/curlx/strcopy.h \ |
| ../lib/curlx/strerr.h \ | |
| ../lib/curlx/strparse.h \ | |
| ../lib/curlx/timediff.h \ | |
| @@ -108,9 +108,7 @@ static void memory_tracking_init(void) | |
| if(env) { | |
| /* use the value as filename */ | |
| char fname[512]; | |
| - | if(strlen(env) >= sizeof(fname)) |
| - | env[sizeof(fname) - 1] = '\0'; |
| - | strcpy(fname, env); |
| + | curlx_strcopy(fname, sizeof(fname), env, strlen(env)); |
| curl_free(env); | |
| curl_dbg_memdebug(fname); | |
| /* this weird stuff here is to make curl_free() get called before | |
| @@ -29,13 +29,13 @@ | |
| /* The point of this function would be to return a string of the input data, | |
| 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) |
| + | static char *max5data(curl_off_t bytes, char *max5, size_t mlen) |
| { | |
| /* a signed 64-bit value is 8192 petabytes maximum */ | |
| - | const char unit[] = { 'k', 'M', 'G', 'T', 'P', 0 }; |
| + | const char unit[] = { 'k', 'M', 'G', 'T', 'P', 'E', 0 }; |
| int k = 0; | |
| if(bytes < 100000) { | |
| - | curl_msnprintf(max5, 6, "%5" CURL_FORMAT_CURL_OFF_T, bytes); |
| + | curl_msnprintf(max5, mlen, "%5" CURL_FORMAT_CURL_OFF_T, bytes); |
| return max5; | |
| } | |
| @@ -43,14 +43,14 @@ static char *max5data(curl_off_t bytes, char *max5) | |
| curl_off_t nbytes = bytes / 1024; | |
| if(nbytes < 100) { | |
| /* display with a decimal */ | |
| - | curl_msnprintf(max5, 6, "%2" CURL_FORMAT_CURL_OFF_T ".%0" |
| + | curl_msnprintf(max5, mlen, "%2" CURL_FORMAT_CURL_OFF_T ".%0" |
| CURL_FORMAT_CURL_OFF_T "%c", bytes / 1024, | |
| (bytes % 1024) / (1024 / 10), unit[k]); | |
| break; | |
| } | |
| else if(nbytes < 10000) { | |
| /* no decimals */ | |
| - | curl_msnprintf(max5, 6, "%4" CURL_FORMAT_CURL_OFF_T "%c", nbytes, |
| + | curl_msnprintf(max5, mlen, "%4" CURL_FORMAT_CURL_OFF_T "%c", nbytes, |
| unit[k]); | |
| break; | |
| } | |
| @@ -87,18 +87,18 @@ int xferinfo_cb(void *clientp, | |
| /* Provide a string that is 2 + 1 + 2 + 1 + 2 = 8 letters long (plus the zero | |
| byte) */ | |
| - | static void time2str(char *r, curl_off_t seconds) |
| + | static void time2str(char *r, size_t rlen, curl_off_t seconds) |
| { | |
| curl_off_t h; | |
| if(seconds <= 0) { | |
| - | strcpy(r, "--:--:--"); |
| + | curlx_strcopy(r, rlen, "--:--:--", 8); |
| return; | |
| } | |
| h = seconds / 3600; | |
| if(h <= 99) { | |
| curl_off_t m = (seconds - (h * 3600)) / 60; | |
| curl_off_t s = (seconds - (h * 3600)) - (m * 60); | |
| - | curl_msnprintf(r, 9, "%2" CURL_FORMAT_CURL_OFF_T |
| + | curl_msnprintf(r, rlen, "%2" CURL_FORMAT_CURL_OFF_T |
| ":%02" CURL_FORMAT_CURL_OFF_T | |
| ":%02" CURL_FORMAT_CURL_OFF_T, h, m, s); | |
| } | |
| @@ -108,10 +108,10 @@ static void time2str(char *r, curl_off_t seconds) | |
| curl_off_t d = seconds / 86400; | |
| h = (seconds - (d * 86400)) / 3600; | |
| if(d <= 999) | |
| - | curl_msnprintf(r, 9, "%3" CURL_FORMAT_CURL_OFF_T |
| + | curl_msnprintf(r, rlen, "%3" CURL_FORMAT_CURL_OFF_T |
| "d %02" CURL_FORMAT_CURL_OFF_T "h", d, h); | |
| else | |
| - | curl_msnprintf(r, 9, "%7" CURL_FORMAT_CURL_OFF_T "d", d); |
| + | curl_msnprintf(r, rlen, "%7" CURL_FORMAT_CURL_OFF_T "d", d); |
| } | |
| } | |
| @@ -254,14 +254,14 @@ bool progress_meter(CURLM *multi, struct curltime *start, bool final) | |
| if(dlknown && speed) { | |
| curl_off_t est = all_dltotal / speed; | |
| curl_off_t left = (all_dltotal - all_dlnow) / speed; | |
| - | time2str(time_left, left); |
| - | time2str(time_total, est); |
| + | time2str(time_left, sizeof(time_left), left); |
| + | time2str(time_total, sizeof(time_total), est); |
| } | |
| else { | |
| - | time2str(time_left, 0); |
| - | time2str(time_total, 0); |
| + | time2str(time_left, sizeof(time_left), 0); |
| + | time2str(time_total, sizeof(time_total), 0); |
| } | |
| - | time2str(time_spent, spent); |
| + | time2str(time_spent, sizeof(time_spent), spent); |
| (void)curl_multi_get_offt(multi, CURLMINFO_XFERS_ADDED, &xfers_added); | |
| (void)curl_multi_get_offt(multi, CURLMINFO_XFERS_RUNNING, &xfers_running); | |
| @@ -281,14 +281,14 @@ bool progress_meter(CURLM *multi, struct curltime *start, bool final) | |
| dlpercen, /* 3 letters */ | |
| ulpercen, /* 3 letters */ | |
| - | max5data(all_dlnow, buffer[0]), |
| - | max5data(all_ulnow, buffer[1]), |
| + | max5data(all_dlnow, buffer[0], sizeof(buffer[0])), |
| + | max5data(all_ulnow, buffer[1], sizeof(buffer[1])), |
| xfers_added, | |
| xfers_running, | |
| time_total, | |
| time_spent, | |
| time_left, | |
| - | max5data(speed, buffer[2]), /* speed */ |
| + | max5data(speed, buffer[2], sizeof(buffer[2])), /* speed */ |
| final ? "\n" : ""); | |
| return TRUE; | |
| } | |
| @@ -37,6 +37,7 @@ CURLX_C = \ | |
| ../../lib/curl_threads.c \ | |
| ../../lib/curlx/fopen.c \ | |
| ../../lib/curlx/multibyte.c \ | |
| + | ../../lib/curlx/strcopy.c \ |
| ../../lib/curlx/strerr.c \ | |
| ../../lib/curlx/strparse.c \ | |
| ../../lib/curlx/timediff.c \ | |
| @@ -40,6 +40,7 @@ CURLX_C = \ | |
| ../../lib/curlx/inet_pton.c \ | |
| ../../lib/curlx/multibyte.c \ | |
| ../../lib/curlx/nonblock.c \ | |
| + | ../../lib/curlx/strcopy.c \ |
| ../../lib/curlx/strerr.c \ | |
| ../../lib/curlx/strparse.c \ | |
| ../../lib/curlx/timediff.c \ | |