From: Michael R Sweet Date: Thu, 25 Jan 2024 02:22:55 +0000 (-0500) Subject: Copy string copy/concat/format changes from libcups v3. X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=f6cb90bf6ef3f81147041016601b8386dc5aedc3;p=thirdparty%2Fcups.git Copy string copy/concat/format changes from libcups v3. Remove all unnecessary string function checks. Remove old snprintf emulation functions (now require C99 which always has it) --- diff --git a/config-scripts/cups-common.m4 b/config-scripts/cups-common.m4 index 3209032c1e..78ed916d28 100644 --- a/config-scripts/cups-common.m4 +++ b/config-scripts/cups-common.m4 @@ -155,11 +155,6 @@ AC_CHECK_HEADER([sys/statvfs.h], AC_DEFINE([HAVE_SYS_STATVFS_H], [1], [Have header?])) AC_CHECK_FUNCS([statfs statvfs]) -dnl Checks for string functions. -dnl TODO: Remove strdup, snprintf, and vsnprintf checks since they are C99? -AC_CHECK_FUNCS([strdup snprintf vsnprintf]) -AC_CHECK_FUNCS([cupsConcatString cupsCopyString]) - dnl Check for random number functions... AC_CHECK_FUNCS([random lrand48 arc4random]) diff --git a/config.h.in b/config.h.in index 5a0e05b7a5..6dc6ef49c5 100644 --- a/config.h.in +++ b/config.h.in @@ -1,7 +1,7 @@ /* * Configuration file for CUPS. * - * Copyright © 2020-2023 by OpenPrinting + * Copyright © 2020-2024 by OpenPrinting * Copyright © 2007-2019 by Apple Inc. * Copyright © 1997-2007 by Easy Software Products. * @@ -177,15 +177,6 @@ #endif /* !HAVE_STRTOLL */ -/* - * Do we have the strXXX() functions? - */ - -#undef HAVE_STRDUP -#undef HAVE_STRLCAT -#undef HAVE_STRLCPY - - /* * Do we have the geteuid() function? */ @@ -214,14 +205,6 @@ #undef HAVE_SYSTEMD_SD_JOURNAL_H -/* - * Do we have the (v)snprintf() functions? - */ - -#undef HAVE_SNPRINTF -#undef HAVE_VSNPRINTF - - /* * What wait functions to use? */ diff --git a/configure b/configure index 4560943f7c..e238272e1c 100755 --- a/configure +++ b/configure @@ -6235,39 +6235,6 @@ then : fi -ac_fn_c_check_func "$LINENO" "strdup" "ac_cv_func_strdup" -if test "x$ac_cv_func_strdup" = xyes -then : - printf "%s\n" "#define HAVE_STRDUP 1" >>confdefs.h - -fi -ac_fn_c_check_func "$LINENO" "snprintf" "ac_cv_func_snprintf" -if test "x$ac_cv_func_snprintf" = xyes -then : - printf "%s\n" "#define HAVE_SNPRINTF 1" >>confdefs.h - -fi -ac_fn_c_check_func "$LINENO" "vsnprintf" "ac_cv_func_vsnprintf" -if test "x$ac_cv_func_vsnprintf" = xyes -then : - printf "%s\n" "#define HAVE_VSNPRINTF 1" >>confdefs.h - -fi - -ac_fn_c_check_func "$LINENO" "cupsConcatString" "ac_cv_func_cupsConcatString" -if test "x$ac_cv_func_cupsConcatString" = xyes -then : - printf "%s\n" "#define HAVE_CUPSCONCATSTRING 1" >>confdefs.h - -fi -ac_fn_c_check_func "$LINENO" "cupsCopyString" "ac_cv_func_cupsCopyString" -if test "x$ac_cv_func_cupsCopyString" = xyes -then : - printf "%s\n" "#define HAVE_CUPSCOPYSTRING 1" >>confdefs.h - -fi - - ac_fn_c_check_func "$LINENO" "random" "ac_cv_func_random" if test "x$ac_cv_func_random" = xyes then : diff --git a/cups/Dependencies b/cups/Dependencies index f5cf443288..16fdddd93c 100644 --- a/cups/Dependencies +++ b/cups/Dependencies @@ -816,7 +816,6 @@ request.o: request.c cups-private.h string-private.h ../config.h \ \ language-private.h ../cups/transcode.h pwg-private.h ../cups/pwg.h \ thread.h cups.h -snprintf.o: snprintf.c string-private.h ../config.h ../cups/base.h string.o: string.c cups-private.h string-private.h ../config.h \ ../cups/base.h debug-internal.h debug-private.h ipp-private.h \ ../cups/cups.h file.h base.h ipp.h http.h array.h language.h pwg.h \ @@ -1505,7 +1504,8 @@ testdest.o: testdest.c cups.h file.h base.h ipp.h http.h array.h \ testdnssd.o: testdnssd.c test-internal.h dnssd.h cups.h file.h base.h \ ipp.h http.h array.h language.h pwg.h thread.h testfile.o: testfile.c string-private.h ../config.h ../cups/base.h \ - debug-private.h file.h base.h dir.h + debug-private.h cups.h file.h base.h ipp.h http.h array.h language.h \ + pwg.h dir.h test-internal.h testform.o: testform.c form.h cups.h file.h base.h ipp.h http.h array.h \ language.h pwg.h test-internal.h testgetdests.o: testgetdests.c cups.h file.h base.h ipp.h http.h array.h \ diff --git a/cups/Makefile b/cups/Makefile index 5596d6315b..c79b93cb1c 100644 --- a/cups/Makefile +++ b/cups/Makefile @@ -53,7 +53,6 @@ COREOBJS = \ raster-stream.o \ raster-stubs.o \ request.o \ - snprintf.o \ string.o \ tempfile.o \ thread.o \ @@ -474,8 +473,7 @@ libcups2.def: $(LIBOBJS) $(IMAGEOBJS) Makefile echo "VERSION 2.15" >>libcups2.def echo "EXPORTS" >>libcups2.def (nm $(LIBOBJS) $(IMAGEOBJS) 2>/dev/null | grep "T _" | awk '{print $$3}'; \ - echo __cups_strcpy; echo __cups_cupsConcatString; echo __cups_cupsCopyString; \ - echo __cups_snprintf; echo __cups_vsnprintf; echo __cups_gettimeofday) | \ + echo __cups_strcpy; echo __cups_gettimeofday) | \ grep -v -E \ -e 'cups_debug|Apple|BackChannel|Backend|FileCheck|Filter|GSSService|SetNegotiate|SideChannel|SNMP' \ -e 'Block$$' | \ diff --git a/cups/cups.h b/cups/cups.h index 7f6d83d8f1..9cb0739473 100644 --- a/cups/cups.h +++ b/cups/cups.h @@ -419,6 +419,8 @@ extern ipp_attribute_t *cupsFindDestReady(http_t *http, cups_dest_t *dest, cups_ extern ipp_attribute_t *cupsFindDestSupported(http_t *http, cups_dest_t *dest, cups_dinfo_t *dinfo, const char *option) _CUPS_PUBLIC; extern ipp_status_t cupsFinishDestDocument(http_t *http, cups_dest_t *dest, cups_dinfo_t *info) _CUPS_PUBLIC; extern ipp_status_t cupsFinishDocument(http_t *http, const char *name) _CUPS_PUBLIC; +extern ssize_t cupsFormatString(char *buffer, size_t bufsize, const char *format, ...) _CUPS_FORMAT(3,4) _CUPS_PUBLIC; +extern ssize_t cupsFormatStringv(char *buffer, size_t bufsize, const char *format, va_list ap) _CUPS_PUBLIC; extern void cupsFreeDestInfo(cups_dinfo_t *dinfo) _CUPS_PUBLIC; extern void cupsFreeDests(int num_dests, cups_dest_t *dests) _CUPS_PUBLIC; extern void cupsFreeJobs(int num_jobs, cups_job_t *jobs) _CUPS_PUBLIC; diff --git a/cups/debug.c b/cups/debug.c index 031efb71ae..3143780cd3 100644 --- a/cups/debug.c +++ b/cups/debug.c @@ -135,7 +135,7 @@ _cups_debug_printf(const char *format, /* I - Printf-style format string */ (int)(curtime.tv_sec % 60), (int)(curtime.tv_usec / 1000)); va_start(ap, format); - bytes = _cups_safe_vsnprintf(buffer + 19, sizeof(buffer) - 20, format, ap) + 19; + bytes = cupsFormatStringv(buffer + 19, sizeof(buffer) - 20, format, ap) + 19; va_end(ap); if ((size_t)bytes >= (sizeof(buffer) - 1)) @@ -332,324 +332,3 @@ _cups_debug_set(const char *logfile, /* I - Log file or NULL */ (void)force; } #endif /* DEBUG */ - - -/* - * '_cups_safe_vsnprintf()' - Format a string into a fixed size buffer, - * quoting special characters. - */ - -ssize_t /* O - Number of bytes formatted */ -_cups_safe_vsnprintf( - char *buffer, /* O - Output buffer */ - size_t bufsize, /* O - Size of output buffer */ - const char *format, /* I - printf-style format string */ - va_list ap) /* I - Pointer to additional arguments */ -{ - char *bufptr, /* Pointer to position in buffer */ - *bufend, /* Pointer to end of buffer */ - size, /* Size character (h, l, L) */ - type; /* Format type character */ - int width, /* Width of field */ - prec; /* Number of characters of precision */ - char tformat[100], /* Temporary format string for snprintf() */ - *tptr, /* Pointer into temporary format */ - temp[1024]; /* Buffer for formatted numbers */ - char *s; /* Pointer to string */ - ssize_t bytes; /* Total number of bytes needed */ - - - if (!buffer || bufsize < 2 || !format) - return (-1); - - /* - * Loop through the format string, formatting as needed... - */ - - bufptr = buffer; - bufend = buffer + bufsize - 1; - bytes = 0; - - while (*format) - { - if (*format == '%') - { - tptr = tformat; - *tptr++ = *format++; - - if (*format == '%') - { - if (bufptr < bufend) - *bufptr++ = *format; - bytes ++; - format ++; - continue; - } - else if (strchr(" -+#\'", *format)) - *tptr++ = *format++; - - if (*format == '*') - { - /* - * Get width from argument... - */ - - format ++; - width = va_arg(ap, int); - - snprintf(tptr, sizeof(tformat) - (size_t)(tptr - tformat), "%d", width); - tptr += strlen(tptr); - } - else - { - width = 0; - - while (isdigit(*format & 255)) - { - if (tptr < (tformat + sizeof(tformat) - 1)) - *tptr++ = *format; - - width = width * 10 + *format++ - '0'; - } - } - - if (*format == '.') - { - if (tptr < (tformat + sizeof(tformat) - 1)) - *tptr++ = *format; - - format ++; - - if (*format == '*') - { - /* - * Get precision from argument... - */ - - format ++; - prec = va_arg(ap, int); - - snprintf(tptr, sizeof(tformat) - (size_t)(tptr - tformat), "%d", prec); - tptr += strlen(tptr); - } - else - { - prec = 0; - - while (isdigit(*format & 255)) - { - if (tptr < (tformat + sizeof(tformat) - 1)) - *tptr++ = *format; - - prec = prec * 10 + *format++ - '0'; - } - } - } - - if (*format == 'l' && format[1] == 'l') - { - size = 'L'; - - if (tptr < (tformat + sizeof(tformat) - 2)) - { - *tptr++ = 'l'; - *tptr++ = 'l'; - } - - format += 2; - } - else if (*format == 'h' || *format == 'l' || *format == 'L') - { - if (tptr < (tformat + sizeof(tformat) - 1)) - *tptr++ = *format; - - size = *format++; - } - else - size = 0; - - if (!*format) - break; - - if (tptr < (tformat + sizeof(tformat) - 1)) - *tptr++ = *format; - - type = *format++; - *tptr = '\0'; - - switch (type) - { - case 'E' : /* Floating point formats */ - case 'G' : - case 'e' : - case 'f' : - case 'g' : - if ((size_t)(width + 2) > sizeof(temp)) - break; - - snprintf(temp, sizeof(temp), tformat, va_arg(ap, double)); - - bytes += (int)strlen(temp); - - if (bufptr) - { - cupsCopyString(bufptr, temp, (size_t)(bufend - bufptr)); - bufptr += strlen(bufptr); - } - break; - - case 'B' : /* Integer formats */ - case 'X' : - case 'b' : - case 'd' : - case 'i' : - case 'o' : - case 'u' : - case 'x' : - if ((size_t)(width + 2) > sizeof(temp)) - break; - -# ifdef HAVE_LONG_LONG - if (size == 'L') - snprintf(temp, sizeof(temp), tformat, va_arg(ap, long long)); - else -# endif /* HAVE_LONG_LONG */ - if (size == 'l') - snprintf(temp, sizeof(temp), tformat, va_arg(ap, long)); - else - snprintf(temp, sizeof(temp), tformat, va_arg(ap, int)); - - bytes += (int)strlen(temp); - - if (bufptr) - { - cupsCopyString(bufptr, temp, (size_t)(bufend - bufptr)); - bufptr += strlen(bufptr); - } - break; - - case 'p' : /* Pointer value */ - if ((size_t)(width + 2) > sizeof(temp)) - break; - - snprintf(temp, sizeof(temp), tformat, va_arg(ap, void *)); - - bytes += (int)strlen(temp); - - if (bufptr) - { - cupsCopyString(bufptr, temp, (size_t)(bufend - bufptr)); - bufptr += strlen(bufptr); - } - break; - - case 'c' : /* Character or character array */ - bytes += width; - - if (bufptr) - { - if (width <= 1) - *bufptr++ = (char)va_arg(ap, int); - else - { - if ((bufptr + width) > bufend) - width = (int)(bufend - bufptr); - - memcpy(bufptr, va_arg(ap, char *), (size_t)width); - bufptr += width; - } - } - break; - - case 's' : /* String */ - if ((s = va_arg(ap, char *)) == NULL) - s = "(null)"; - - /* - * Copy the C string, replacing control chars and \ with - * C character escapes... - */ - - for (bufend --; *s && bufptr < bufend; s ++) - { - if (*s == '\n') - { - *bufptr++ = '\\'; - *bufptr++ = 'n'; - bytes += 2; - } - else if (*s == '\r') - { - *bufptr++ = '\\'; - *bufptr++ = 'r'; - bytes += 2; - } - else if (*s == '\t') - { - *bufptr++ = '\\'; - *bufptr++ = 't'; - bytes += 2; - } - else if (*s == '\\') - { - *bufptr++ = '\\'; - *bufptr++ = '\\'; - bytes += 2; - } - else if (*s == '\'') - { - *bufptr++ = '\\'; - *bufptr++ = '\''; - bytes += 2; - } - else if (*s == '\"') - { - *bufptr++ = '\\'; - *bufptr++ = '\"'; - bytes += 2; - } - else if ((*s & 255) < ' ') - { - if ((bufptr + 2) >= bufend) - break; - - *bufptr++ = '\\'; - *bufptr++ = '0'; - *bufptr++ = '0' + *s / 8; - *bufptr++ = '0' + (*s & 7); - bytes += 4; - } - else - { - *bufptr++ = *s; - bytes ++; - } - } - - bufend ++; - break; - - case 'n' : /* Output number of chars so far */ - *(va_arg(ap, int *)) = (int)bytes; - break; - } - } - else - { - bytes ++; - - if (bufptr < bufend) - *bufptr++ = *format; - - format ++; - } - } - - /* - * Nul-terminate the string and return the number of characters needed. - */ - - *bufptr = '\0'; - - return (bytes); -} diff --git a/cups/snprintf.c b/cups/snprintf.c deleted file mode 100644 index 4d9f650144..0000000000 --- a/cups/snprintf.c +++ /dev/null @@ -1,355 +0,0 @@ -/* - * snprintf functions for CUPS. - * - * Copyright © 2021-2023 by OpenPrinting - * Copyright © 2007-2019 by Apple Inc. - * Copyright © 1997-2007 by Easy Software Products. - * - * Licensed under Apache License v2.0. See the file "LICENSE" for more - * information. - */ - -/* - * Include necessary headers... - */ - -#include "string-private.h" - - -#ifndef HAVE_VSNPRINTF -/* - * '_cups_vsnprintf()' - Format a string into a fixed size buffer. - */ - -int /* O - Number of bytes formatted */ -_cups_vsnprintf(char *buffer, /* O - Output buffer */ - size_t bufsize, /* O - Size of output buffer */ - const char *format, /* I - printf-style format string */ - va_list ap) /* I - Pointer to additional arguments */ -{ - char *bufptr, /* Pointer to position in buffer */ - *bufend, /* Pointer to end of buffer */ - sign, /* Sign of format width */ - size, /* Size character (h, l, L) */ - type; /* Format type character */ - int width, /* Width of field */ - prec; /* Number of characters of precision */ - char tformat[100], /* Temporary format string for sprintf() */ - *tptr, /* Pointer into temporary format */ - temp[1024]; /* Buffer for formatted numbers */ - size_t templen; /* Length of "temp" */ - char *s; /* Pointer to string */ - int slen; /* Length of string */ - int bytes; /* Total number of bytes needed */ - - - /* - * Loop through the format string, formatting as needed... - */ - - bufptr = buffer; - bufend = buffer + bufsize - 1; - bytes = 0; - - while (*format) - { - if (*format == '%') - { - tptr = tformat; - *tptr++ = *format++; - - if (*format == '%') - { - if (bufptr && bufptr < bufend) *bufptr++ = *format; - bytes ++; - format ++; - continue; - } - else if (strchr(" -+#\'", *format)) - { - *tptr++ = *format; - sign = *format++; - } - else - sign = 0; - - if (*format == '*') - { - /* - * Get width from argument... - */ - - format ++; - width = va_arg(ap, int); - - /* Note: Can't use snprintf here since we are implementing this function... */ - sprintf(tptr, "%d", width); - tptr += strlen(tptr); - } - else - { - width = 0; - - while (isdigit(*format & 255)) - { - if (tptr < (tformat + sizeof(tformat) - 1)) - *tptr++ = *format; - - width = width * 10 + *format++ - '0'; - } - } - - if (*format == '.') - { - if (tptr < (tformat + sizeof(tformat) - 1)) - *tptr++ = *format; - - format ++; - - if (*format == '*') - { - /* - * Get precision from argument... - */ - - format ++; - prec = va_arg(ap, int); - - /* Note: Can't use snprintf here since we are implementing this function... */ - sprintf(tptr, "%d", prec); - tptr += strlen(tptr); - } - else - { - prec = 0; - - while (isdigit(*format & 255)) - { - if (tptr < (tformat + sizeof(tformat) - 1)) - *tptr++ = *format; - - prec = prec * 10 + *format++ - '0'; - } - } - } - else - prec = -1; - - if (*format == 'l' && format[1] == 'l') - { - size = 'L'; - - if (tptr < (tformat + sizeof(tformat) - 2)) - { - *tptr++ = 'l'; - *tptr++ = 'l'; - } - - format += 2; - } - else if (*format == 'h' || *format == 'l' || *format == 'L') - { - if (tptr < (tformat + sizeof(tformat) - 1)) - *tptr++ = *format; - - size = *format++; - } - - if (!*format) - break; - - if (tptr < (tformat + sizeof(tformat) - 1)) - *tptr++ = *format; - - type = *format++; - *tptr = '\0'; - - switch (type) - { - case 'E' : /* Floating point formats */ - case 'G' : - case 'e' : - case 'f' : - case 'g' : - if ((width + 2) > sizeof(temp)) - break; - - /* Note: Can't use snprintf here since we are implementing this function... */ - sprintf(temp, tformat, va_arg(ap, double)); - templen = strlen(temp); - - bytes += (int)templen; - - if (bufptr) - { - if ((bufptr + templen) > bufend) - { - cupsCopyString(bufptr, temp, (size_t)(bufend - bufptr)); - bufptr = bufend; - } - else - { - memcpy(bufptr, temp, templen + 1); - bufptr += templen; - } - } - break; - - case 'B' : /* Integer formats */ - case 'X' : - case 'b' : - case 'd' : - case 'i' : - case 'o' : - case 'u' : - case 'x' : - if ((width + 2) > sizeof(temp)) - break; - - /* Note: Can't use snprintf here since we are implementing this function... */ - sprintf(temp, tformat, va_arg(ap, int)); - templen = strlen(temp); - - bytes += (int)templen; - - if (bufptr) - { - if ((bufptr + templen) > bufend) - { - cupsCopyString(bufptr, temp, (size_t)(bufend - bufptr)); - bufptr = bufend; - } - else - { - memcpy(bufptr, temp, templen + 1); - bufptr += templen; - } - } - break; - - case 'p' : /* Pointer value */ - if ((width + 2) > sizeof(temp)) - break; - - /* Note: Can't use snprintf here since we are implementing this function... */ - sprintf(temp, tformat, va_arg(ap, void *)); - templen = strlen(temp); - - bytes += (int)templen; - - if (bufptr) - { - if ((bufptr + templen) > bufend) - { - cupsCopyString(bufptr, temp, (size_t)(bufend - bufptr)); - bufptr = bufend; - } - else - { - memcpy(bufptr, temp, templen + 1); - bufptr += templen; - } - } - break; - - case 'c' : /* Character or character array */ - bytes += width; - - if (bufptr) - { - if (width <= 1) - *bufptr++ = va_arg(ap, int); - else - { - if ((bufptr + width) > bufend) - width = (int)(bufend - bufptr); - - memcpy(bufptr, va_arg(ap, char *), (size_t)width); - bufptr += width; - } - } - break; - - case 's' : /* String */ - if ((s = va_arg(ap, char *)) == NULL) - s = "(null)"; - - slen = (int)strlen(s); - if (slen > width && prec != width) - width = slen; - - bytes += width; - - if (bufptr) - { - if ((bufptr + width) > bufend) - width = (int)(bufend - bufptr); - - if (slen > width) - slen = width; - - if (sign == '-') - { - memcpy(bufptr, s, (size_t)slen); - memset(bufptr + slen, ' ', (size_t)(width - slen)); - } - else - { - memset(bufptr, ' ', (size_t)(width - slen)); - memcpy(bufptr + width - slen, s, (size_t)slen); - } - - bufptr += width; - } - break; - - case 'n' : /* Output number of chars so far */ - *(va_arg(ap, int *)) = bytes; - break; - } - } - else - { - bytes ++; - - if (bufptr && bufptr < bufend) - *bufptr++ = *format; - - format ++; - } - } - - /* - * Nul-terminate the string and return the number of characters needed. - */ - - if (bufptr && bufptr < bufend) - *bufptr = '\0'; - - return (bytes); -} -#endif /* !HAVE_VSNPRINT */ - - -#ifndef HAVE_SNPRINTF -/* - * '_cups_snprintf()' - Format a string into a fixed size buffer. - */ - -int /* O - Number of bytes formatted */ -_cups_snprintf(char *buffer, /* O - Output buffer */ - size_t bufsize, /* O - Size of output buffer */ - const char *format, /* I - printf-style format string */ - ...) /* I - Additional arguments as needed */ -{ - int bytes; /* Number of bytes formatted */ - va_list ap; /* Pointer to additional arguments */ - - - va_start(ap, format); - bytes = vsnprintf(buffer, bufsize, format, ap); - va_end(ap); - - return (bytes); -} -#endif /* !HAVE_SNPRINTF */ diff --git a/cups/string-private.h b/cups/string-private.h index 7b0abfbc60..e76d20d70c 100644 --- a/cups/string-private.h +++ b/cups/string-private.h @@ -125,7 +125,6 @@ extern int _cups_toupper(int ch); // Functions... // -extern ssize_t _cups_safe_vsnprintf(char *buffer, size_t bufsize, const char *format, va_list args) _CUPS_PRIVATE; extern void _cups_strcpy(char *dst, const char *src) _CUPS_PRIVATE; extern int _cups_strcasecmp(const char *, const char *) _CUPS_PRIVATE; extern int _cups_strncasecmp(const char *, const char *, size_t n) _CUPS_PRIVATE; diff --git a/cups/string.c b/cups/string.c index cd68ff6f02..1e469a125b 100644 --- a/cups/string.c +++ b/cups/string.c @@ -9,10 +9,6 @@ * information. */ -/* - * Include necessary headers... - */ - #define _CUPS_STRING_C_ #include "cups-private.h" #include "debug-internal.h" @@ -35,10 +31,13 @@ static cups_array_t *stringpool = NULL; */ static int compare_sp_items(_cups_sp_item_t *a, _cups_sp_item_t *b); +static void validate_end(char *s, char *end); // -// 'cupsConcatString()' - Safely concatenate two strings. +// 'cupsConcatString()' - Safely concatenate two UTF-8 strings. +// +// @since CUPS 2.5@ // size_t // O - Length of string @@ -46,18 +45,14 @@ cupsConcatString(char *dst, // O - Destination string const char *src, // I - Source string size_t dstsize) // I - Size of destination string buffer { - // Range check input... - if (!dst || !src || dstsize == 0) - return (0); - -#ifdef HAVE_STRLCAT - return (strlcat(dst, src, dstsize)); - -#else size_t srclen; // Length of source string size_t dstlen; // Length of destination string + // Range check input... + if (!dst || !src || dstsize == 0) + return (0); + // Figure out how much room is left... dstlen = strlen(dst); @@ -70,19 +65,29 @@ cupsConcatString(char *dst, // O - Destination string srclen = strlen(src); // Copy the appropriate amount... - if (srclen > dstsize) - srclen = dstsize; + if (srclen <= dstsize) + { + // String fits, just copy over... + memmove(dst + dstlen, src, srclen); + dst[dstlen + srclen] = '\0'; + } + else + { + // String too big, copy what we can and clean up the end... + memmove(dst + dstlen, src, dstsize); + dst[dstlen + dstsize] = '\0'; - memmove(dst + dstlen, src, srclen); - dst[dstlen + srclen] = '\0'; + validate_end(dst, dst + dstlen + dstsize); + } return (dstlen + srclen); -#endif // HAVE_STRLCAT } // -// 'cupsCopyString()' - Safely copy two strings. +// 'cupsCopyString()' - Safely copy a UTF-8 string. +// +// @since CUPS 2.5@ // size_t // O - Length of string @@ -90,6 +95,9 @@ cupsCopyString(char *dst, // O - Destination string const char *src, // I - Source string size_t dstsize) // I - Size of destination string buffer { + size_t srclen; // Length of source string + + // Range check input... if (!dst || !src || dstsize == 0) { @@ -98,26 +106,398 @@ cupsCopyString(char *dst, // O - Destination string return (0); } -#ifdef HAVE_STRLCPY - return (strlcpy(dst, src, dstsize)); - -#else - size_t srclen; // Length of source string - // Figure out how much room is needed... dstsize --; srclen = strlen(src); // Copy the appropriate amount... - if (srclen > dstsize) - srclen = dstsize; + if (srclen <= dstsize) + { + // Source string will fit... + memmove(dst, src, srclen); + dst[srclen] = '\0'; + } + else + { + // Source string too big, copy what we can and clean up the end... + memmove(dst, src, dstsize); + dst[dstsize] = '\0'; - memmove(dst, src, srclen); - dst[srclen] = '\0'; + validate_end(dst, dst + dstsize); + } return (srclen); -#endif // HAVE_STRLCPY +} + + +// +// 'cupsFormatString()' - Format a UTF-8 string into a fixed size buffer. +// +// This function formats a UTF-8 string into a fixed size buffer, escaping +// special/control characters as needed so they can be safely displayed or +// logged. +// +// @since CUPS 2.5@ +// + +ssize_t // O - Number of bytes formatted +cupsFormatString( + char *buffer, // O - Output buffer + size_t bufsize, // O - Size of output buffer + const char *format, // I - `printf`-style format string + ...) // I - Additional arguments +{ + va_list ap; // Pointer to additional arguments + ssize_t ret; // Return value + + + // Range check input... + if (!buffer || bufsize < 2 || !format) + return (-1); + + // Format the string... + va_start(ap, format); + ret = cupsFormatStringv(buffer, bufsize, format, ap); + va_end(ap); + + // Return the number of bytes that could have been written... + return (ret); +} + + +// +// 'cupsFormatStringv()' - Format a UTF-8 string into a fixed size buffer (`va_list` version). +// +// This function formats a UTF-8 string into a fixed size buffer using a +// variable argument pointer, escaping special/control characters as needed so +// they can be safely displayed or logged. +// +// @since CUPS 2.5@ +// + +ssize_t // O - Number of bytes formatted +cupsFormatStringv( + char *buffer, // O - Output buffer + size_t bufsize, // O - Size of output buffer + const char *format, // I - printf-style format string + va_list ap) // I - Pointer to additional arguments +{ + char *bufptr, // Pointer to position in buffer + *bufend, // Pointer to end of buffer + size, // Size character (h, l, L) + type; // Format type character + int width, // Width of field + prec; // Number of characters of precision + char tformat[100], // Temporary format string for snprintf() + *tptr, // Pointer into temporary format + temp[1024]; // Buffer for formatted numbers + char *s; // Pointer to string + ssize_t bytes; // Total number of bytes needed + + + // Range check input... + if (!buffer || bufsize < 2 || !format || !ap) + return (-1); + + // Loop through the format string, formatting as needed... + bufptr = buffer; + bufend = buffer + bufsize - 1; + bytes = 0; + + while (*format) + { + if (*format == '%') + { + // Format character... + tptr = tformat; + *tptr++ = *format++; + + if (*format == '%') + { + if (bufptr < bufend) + *bufptr++ = *format; + bytes ++; + format ++; + continue; + } + else if (strchr(" -+#\'", *format)) + { + *tptr++ = *format++; + } + + if (*format == '*') + { + // Get width from argument... + format ++; + width = va_arg(ap, int); + + snprintf(tptr, sizeof(tformat) - (size_t)(tptr - tformat), "%d", width); + tptr += strlen(tptr); + } + else + { + width = 0; + + while (isdigit(*format & 255)) + { + if (tptr < (tformat + sizeof(tformat) - 1)) + *tptr++ = *format; + + width = width * 10 + *format++ - '0'; + } + } + + if (*format == '.') + { + if (tptr < (tformat + sizeof(tformat) - 1)) + *tptr++ = *format; + + format ++; + + if (*format == '*') + { + // Get precision from argument... + format ++; + prec = va_arg(ap, int); + + snprintf(tptr, sizeof(tformat) - (size_t)(tptr - tformat), "%d", prec); + tptr += strlen(tptr); + } + else + { + prec = 0; + + while (isdigit(*format & 255)) + { + if (tptr < (tformat + sizeof(tformat) - 1)) + *tptr++ = *format; + + prec = prec * 10 + *format++ - '0'; + } + } + } + + if (*format == 'l' && format[1] == 'l') + { + size = 'L'; + + if (tptr < (tformat + sizeof(tformat) - 2)) + { + *tptr++ = 'l'; + *tptr++ = 'l'; + } + + format += 2; + } + else if (*format == 'h' || *format == 'l' || *format == 'L') + { + if (tptr < (tformat + sizeof(tformat) - 1)) + *tptr++ = *format; + + size = *format++; + } + else + { + size = 0; + } + + if (!*format) + break; + + if (tptr < (tformat + sizeof(tformat) - 1)) + *tptr++ = *format; + + type = *format++; + *tptr = '\0'; + + switch (type) + { + case 'E' : // Floating point formats + case 'G' : + case 'e' : + case 'f' : + case 'g' : + if ((size_t)(width + 2) > sizeof(temp)) + break; + + snprintf(temp, sizeof(temp), tformat, va_arg(ap, double)); + + bytes += (int)strlen(temp); + + if (bufptr < bufend) + { + cupsCopyString(bufptr, temp, (size_t)(bufend - bufptr)); + bufptr += strlen(bufptr); + } + break; + + case 'B' : // Integer formats + case 'X' : + case 'b' : + case 'd' : + case 'i' : + case 'o' : + case 'u' : + case 'x' : + if ((size_t)(width + 2) > sizeof(temp)) + break; + +# ifdef HAVE_LONG_LONG + if (size == 'L') + snprintf(temp, sizeof(temp), tformat, va_arg(ap, long long)); + else +# endif // HAVE_LONG_LONG + if (size == 'l') + snprintf(temp, sizeof(temp), tformat, va_arg(ap, long)); + else + snprintf(temp, sizeof(temp), tformat, va_arg(ap, int)); + + bytes += (int)strlen(temp); + + if (bufptr < bufend) + { + cupsCopyString(bufptr, temp, (size_t)(bufend - bufptr)); + bufptr += strlen(bufptr); + } + break; + + case 'p' : // Pointer value + if ((size_t)(width + 2) > sizeof(temp)) + break; + + snprintf(temp, sizeof(temp), tformat, va_arg(ap, void *)); + + bytes += (int)strlen(temp); + + if (bufptr < bufend) + { + cupsCopyString(bufptr, temp, (size_t)(bufend - bufptr)); + bufptr += strlen(bufptr); + } + break; + + case 'c' : // Character or character array + bytes += width; + + if (bufptr < bufend) + { + if (width <= 1) + { + *bufptr++ = (char)va_arg(ap, int); + } + else + { + if ((bufptr + width) > bufend) + width = (int)(bufend - bufptr); + + memcpy(bufptr, va_arg(ap, char *), (size_t)width); + bufptr += width; + } + } + break; + + case 's' : // String + if ((s = va_arg(ap, char *)) == NULL) + s = "(null)"; + + // Copy the C string, replacing control chars and \ with C character escapes... + for (; *s && bufptr < bufend; s ++) + { + if (*s == '\n') + { + *bufptr++ = '\\'; + if (bufptr < bufend) + *bufptr++ = 'n'; + bytes += 2; + } + else if (*s == '\r') + { + *bufptr++ = '\\'; + if (bufptr < bufend) + *bufptr++ = 'r'; + bytes += 2; + } + else if (*s == '\t') + { + *bufptr++ = '\\'; + if (bufptr < bufend) + *bufptr++ = 't'; + bytes += 2; + } + else if (*s == '\\') + { + *bufptr++ = '\\'; + if (bufptr < bufend) + *bufptr++ = '\\'; + bytes += 2; + } + else if (*s == '\'') + { + *bufptr++ = '\\'; + if (bufptr < bufend) + *bufptr++ = '\''; + bytes += 2; + } + else if (*s == '\"') + { + *bufptr++ = '\\'; + if (bufptr < bufend) + *bufptr++ = '\"'; + bytes += 2; + } + else if ((*s & 255) < ' ') + { + *bufptr++ = '\\'; + if (bufptr < bufend) + *bufptr++ = '0'; + if (bufptr < bufend) + *bufptr++ = '0' + *s / 8; + if (bufptr < bufend) + *bufptr++ = '0' + (*s & 7); + bytes += 4; + } + else + { + *bufptr++ = *s; + bytes ++; + } + } + + if (bufptr >= bufend) + bytes += 2 * strlen(s); + break; + + case 'n' : // Output number of chars so far + *(va_arg(ap, int *)) = (int)bytes; + break; + } + } + else + { + // Literal character... + bytes ++; + + if (bufptr < bufend) + *bufptr++ = *format++; + } + } + + // Nul-terminate the string and return the number of characters needed. + if (bufptr < bufend) + { + // Everything fit in the buffer... + *bufptr = '\0'; + } + else + { + // Make sure the last characters are valid UTF-8... + *bufend = '\0'; + + validate_end(buffer, bufend); + } + + return (bytes); } @@ -821,3 +1201,46 @@ compare_sp_items(_cups_sp_item_t *a, /* I - First item */ { return (strcmp(a->str, b->str)); } + + +// +// 'validate_end()' - Validate the last UTF-8 character in a buffer. +// + +static void +validate_end(char *s, // I - Pointer to start of string + char *end) // I - Pointer to end of string +{ + char *ptr = end - 1; // Pointer into string + + + if (ptr > s && *ptr & 0x80) + { + while ((*ptr & 0xc0) == 0x80 && ptr > s) + ptr --; + + if ((*ptr & 0xe0) == 0xc0) + { + // Verify 2-byte UTF-8 sequence... + if ((end - ptr) != 2) + *ptr = '\0'; + } + else if ((*ptr & 0xf0) == 0xe0) + { + // Verify 3-byte UTF-8 sequence... + if ((end - ptr) != 3) + *ptr = '\0'; + } + else if ((*ptr & 0xf8) == 0xf0) + { + // Verify 4-byte UTF-8 sequence... + if ((end - ptr) != 4) + *ptr = '\0'; + } + else if (*ptr & 0x80) + { + // Invalid sequence at end... + *ptr = '\0'; + } + } +} diff --git a/scheduler/log.c b/scheduler/log.c index cd8a7ef38c..78b11aaced 100644 --- a/scheduler/log.c +++ b/scheduler/log.c @@ -1314,7 +1314,7 @@ format_log_line(const char *message, /* I - Printf-style format string */ * Format the log message... */ - len = _cups_safe_vsnprintf(log_line, log_linesize, message, ap); + len = cupsFormatStringv(log_line, log_linesize, message, ap); /* * Resize the buffer as needed... diff --git a/vcnet/config.h b/vcnet/config.h index 62e5723859..404c249292 100644 --- a/vcnet/config.h +++ b/vcnet/config.h @@ -1,7 +1,7 @@ /* * Configuration file for CUPS on Windows. * - * Copyright © 2021-2023 by OpenPrinting + * Copyright © 2021-2024 by OpenPrinting * Copyright © 2007-2019 by Apple Inc. * Copyright © 1997-2007 by Easy Software Products. * @@ -270,15 +270,6 @@ typedef unsigned long useconds_t; #endif /* !HAVE_STRTOLL */ -/* - * Do we have the strXXX() functions? - */ - -#define HAVE_STRDUP 1 -/* #undef HAVE_STRLCAT */ -/* #undef HAVE_STRLCPY */ - - /* * Do we have the geteuid() function? */ @@ -307,14 +298,6 @@ typedef unsigned long useconds_t; /* #undef HAVE_SYSTEMD_SD_JOURNAL_H */ -/* - * Do we have the (v)snprintf() functions? - */ - -#define HAVE_SNPRINTF 1 -#define HAVE_VSNPRINTF 1 - - /* * What wait functions to use? */ diff --git a/vcnet/libcups2.vcxproj b/vcnet/libcups2.vcxproj index 01e6db5ab6..f7143fe0e7 100644 --- a/vcnet/libcups2.vcxproj +++ b/vcnet/libcups2.vcxproj @@ -159,7 +159,6 @@ - diff --git a/xcode/CUPS.xcodeproj/project.pbxproj b/xcode/CUPS.xcodeproj/project.pbxproj index 1049eb5bf6..43857b671e 100644 --- a/xcode/CUPS.xcodeproj/project.pbxproj +++ b/xcode/CUPS.xcodeproj/project.pbxproj @@ -3,7 +3,7 @@ archiveVersion = 1; classes = { }; - objectVersion = 53; + objectVersion = 54; objects = { /* Begin PBXAggregateTarget section */ @@ -156,7 +156,6 @@ 270696271CADF3E200FFE5FB /* pwg-media.c in Sources */ = {isa = PBXBuildFile; fileRef = 72220EF8133305BB00FCA411 /* pwg-media.c */; }; 270696281CADF3E200FFE5FB /* dest-localization.c in Sources */ = {isa = PBXBuildFile; fileRef = 72CF95E118A13543000FCAE4 /* dest-localization.c */; }; 270696291CADF3E200FFE5FB /* request.c in Sources */ = {isa = PBXBuildFile; fileRef = 72220EFB133305BB00FCA411 /* request.c */; }; - 2706962C1CADF3E200FFE5FB /* snprintf.c in Sources */ = {isa = PBXBuildFile; fileRef = 72220F00133305BB00FCA411 /* snprintf.c */; }; 2706962D1CADF3E200FFE5FB /* string.c in Sources */ = {isa = PBXBuildFile; fileRef = 72220F02133305BB00FCA411 /* string.c */; }; 2706962E1CADF3E200FFE5FB /* tempfile.c in Sources */ = {isa = PBXBuildFile; fileRef = 72220F03133305BB00FCA411 /* tempfile.c */; }; 2706962F1CADF3E200FFE5FB /* thread.c in Sources */ = {isa = PBXBuildFile; fileRef = 72220F05133305BB00FCA411 /* thread.c */; }; @@ -393,7 +392,6 @@ 274FF6AF1333B1C400317ECB /* request.c in Sources */ = {isa = PBXBuildFile; fileRef = 72220EFB133305BB00FCA411 /* request.c */; }; 274FF6B01333B1C400317ECB /* sidechannel.c in Sources */ = {isa = PBXBuildFile; fileRef = 72220EFC133305BB00FCA411 /* sidechannel.c */; }; 274FF6B11333B1C400317ECB /* snmp.c in Sources */ = {isa = PBXBuildFile; fileRef = 72220EFF133305BB00FCA411 /* snmp.c */; }; - 274FF6B21333B1C400317ECB /* snprintf.c in Sources */ = {isa = PBXBuildFile; fileRef = 72220F00133305BB00FCA411 /* snprintf.c */; }; 274FF6B31333B1C400317ECB /* string.c in Sources */ = {isa = PBXBuildFile; fileRef = 72220F02133305BB00FCA411 /* string.c */; }; 274FF6B41333B1C400317ECB /* tempfile.c in Sources */ = {isa = PBXBuildFile; fileRef = 72220F03133305BB00FCA411 /* tempfile.c */; }; 274FF6B51333B1C400317ECB /* thread.c in Sources */ = {isa = PBXBuildFile; fileRef = 72220F05133305BB00FCA411 /* thread.c */; }; @@ -564,7 +562,6 @@ 72220F37133305BB00FCA411 /* sidechannel.h in Headers */ = {isa = PBXBuildFile; fileRef = 72220EFD133305BB00FCA411 /* sidechannel.h */; settings = {ATTRIBUTES = (Public, ); }; }; 72220F38133305BB00FCA411 /* snmp-private.h in Headers */ = {isa = PBXBuildFile; fileRef = 72220EFE133305BB00FCA411 /* snmp-private.h */; settings = {ATTRIBUTES = (Private, ); }; }; 72220F39133305BB00FCA411 /* snmp.c in Sources */ = {isa = PBXBuildFile; fileRef = 72220EFF133305BB00FCA411 /* snmp.c */; }; - 72220F3A133305BB00FCA411 /* snprintf.c in Sources */ = {isa = PBXBuildFile; fileRef = 72220F00133305BB00FCA411 /* snprintf.c */; }; 72220F3B133305BB00FCA411 /* string-private.h in Headers */ = {isa = PBXBuildFile; fileRef = 72220F01133305BB00FCA411 /* string-private.h */; settings = {ATTRIBUTES = (Private, ); }; }; 72220F3C133305BB00FCA411 /* string.c in Sources */ = {isa = PBXBuildFile; fileRef = 72220F02133305BB00FCA411 /* string.c */; }; 72220F3D133305BB00FCA411 /* tempfile.c in Sources */ = {isa = PBXBuildFile; fileRef = 72220F03133305BB00FCA411 /* tempfile.c */; }; @@ -3317,7 +3314,6 @@ 72220EFD133305BB00FCA411 /* sidechannel.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = sidechannel.h; path = ../cups/sidechannel.h; sourceTree = ""; }; 72220EFE133305BB00FCA411 /* snmp-private.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "snmp-private.h"; path = "../cups/snmp-private.h"; sourceTree = ""; }; 72220EFF133305BB00FCA411 /* snmp.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = snmp.c; path = ../cups/snmp.c; sourceTree = ""; }; - 72220F00133305BB00FCA411 /* snprintf.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = snprintf.c; path = ../cups/snprintf.c; sourceTree = ""; }; 72220F01133305BB00FCA411 /* string-private.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "string-private.h"; path = "../cups/string-private.h"; sourceTree = ""; }; 72220F02133305BB00FCA411 /* string.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = string.c; path = ../cups/string.c; sourceTree = ""; }; 72220F03133305BB00FCA411 /* tempfile.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = tempfile.c; path = ../cups/tempfile.c; sourceTree = ""; }; @@ -4920,7 +4916,6 @@ 72220EFB133305BB00FCA411 /* request.c */, 72220EFC133305BB00FCA411 /* sidechannel.c */, 72220EFF133305BB00FCA411 /* snmp.c */, - 72220F00133305BB00FCA411 /* snprintf.c */, 72220F02133305BB00FCA411 /* string.c */, 72220F03133305BB00FCA411 /* tempfile.c */, 27F515452AAFBECF0045EE21 /* test-internal.h */, @@ -7338,7 +7333,6 @@ 270696281CADF3E200FFE5FB /* dest-localization.c in Sources */, 270696291CADF3E200FFE5FB /* request.c in Sources */, 272A5C0F2AA41D6B00027F9B /* dnssd.c in Sources */, - 2706962C1CADF3E200FFE5FB /* snprintf.c in Sources */, 2706962D1CADF3E200FFE5FB /* string.c in Sources */, 7253C455216E980000494ADD /* raster-error.c in Sources */, 2706965B1CAE1A9A00FFE5FB /* util.c in Sources */, @@ -7762,7 +7756,6 @@ 274FF6AF1333B1C400317ECB /* request.c in Sources */, 274FF6B01333B1C400317ECB /* sidechannel.c in Sources */, 274FF6B11333B1C400317ECB /* snmp.c in Sources */, - 274FF6B21333B1C400317ECB /* snprintf.c in Sources */, 274FF6B31333B1C400317ECB /* string.c in Sources */, 274FF6B41333B1C400317ECB /* tempfile.c in Sources */, 274FF6B51333B1C400317ECB /* thread.c in Sources */, @@ -7918,7 +7911,6 @@ 72220F36133305BB00FCA411 /* sidechannel.c in Sources */, 7253C45E216ED51500494ADD /* raster-interstub.c in Sources */, 72220F39133305BB00FCA411 /* snmp.c in Sources */, - 72220F3A133305BB00FCA411 /* snprintf.c in Sources */, 27F515672AB1F7440045EE21 /* form.c in Sources */, 72220F3C133305BB00FCA411 /* string.c in Sources */, 72220F3D133305BB00FCA411 /* tempfile.c in Sources */, diff --git a/xcode/config.h b/xcode/config.h index 108eaf7118..83cc783d76 100644 --- a/xcode/config.h +++ b/xcode/config.h @@ -1,7 +1,7 @@ /* * Configuration file for CUPS and Xcode. * - * Copyright © 2021-2023 by OpenPrinting + * Copyright © 2021-2024 by OpenPrinting * Copyright © 2007-2019 by Apple Inc. * Copyright © 1997-2007 by Easy Software Products. * @@ -190,15 +190,6 @@ #endif /* !HAVE_STRTOLL */ -/* - * Do we have the strXXX() functions? - */ - -#define HAVE_STRDUP 1 -#define HAVE_STRLCAT 1 -#define HAVE_STRLCPY 1 - - /* * Do we have the geteuid() function? */ @@ -227,14 +218,6 @@ /* #undef HAVE_SYSTEMD_SD_JOURNAL_H */ -/* - * Do we have the (v)snprintf() functions? - */ - -#define HAVE_SNPRINTF 1 -#define HAVE_VSNPRINTF 1 - - /* * What wait functions to use? */