Remove all unnecessary string function checks.
Remove old snprintf emulation functions (now require C99 which always has it)
AC_CHECK_HEADER([sys/vfs.h], AC_DEFINE([HAVE_SYS_VFS_H], [1], [Have <sys/vfs.h> 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])
/*
* 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.
*
#endif /* !HAVE_STRTOLL */
-/*
- * Do we have the strXXX() functions?
- */
-
-#undef HAVE_STRDUP
-#undef HAVE_STRLCAT
-#undef HAVE_STRLCPY
-
-
/*
* Do we have the geteuid() function?
*/
#undef HAVE_SYSTEMD_SD_JOURNAL_H
-/*
- * Do we have the (v)snprintf() functions?
- */
-
-#undef HAVE_SNPRINTF
-#undef HAVE_VSNPRINTF
-
-
/*
* What wait functions to use?
*/
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 :
\
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 \
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 \
raster-stream.o \
raster-stubs.o \
request.o \
- snprintf.o \
string.o \
tempfile.o \
thread.o \
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$$' | \
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;
(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))
(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);
-}
+++ /dev/null
-/*
- * 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 */
// 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;
* information.
*/
-/*
- * Include necessary headers...
- */
-
#define _CUPS_STRING_C_
#include "cups-private.h"
#include "debug-internal.h"
*/
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
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);
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
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)
{
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);
}
{
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';
+ }
+ }
+}
* 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...
/*
* 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.
*
#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?
*/
/* #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?
*/
<ClCompile Include="..\cups\raster-stream.c" />
<ClCompile Include="..\cups\raster-stubs.c" />
<ClCompile Include="..\cups\request.c" />
- <ClCompile Include="..\cups\snprintf.c" />
<ClCompile Include="..\cups\string.c" />
<ClCompile Include="..\cups\tempfile.c" />
<ClCompile Include="..\cups\thread.c" />
archiveVersion = 1;
classes = {
};
- objectVersion = 53;
+ objectVersion = 54;
objects = {
/* Begin PBXAggregateTarget section */
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 */; };
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 */; };
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 */; };
72220EFD133305BB00FCA411 /* sidechannel.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = sidechannel.h; path = ../cups/sidechannel.h; sourceTree = "<group>"; };
72220EFE133305BB00FCA411 /* snmp-private.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "snmp-private.h"; path = "../cups/snmp-private.h"; sourceTree = "<group>"; };
72220EFF133305BB00FCA411 /* snmp.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = snmp.c; path = ../cups/snmp.c; sourceTree = "<group>"; };
- 72220F00133305BB00FCA411 /* snprintf.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = snprintf.c; path = ../cups/snprintf.c; sourceTree = "<group>"; };
72220F01133305BB00FCA411 /* string-private.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "string-private.h"; path = "../cups/string-private.h"; sourceTree = "<group>"; };
72220F02133305BB00FCA411 /* string.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = string.c; path = ../cups/string.c; sourceTree = "<group>"; };
72220F03133305BB00FCA411 /* tempfile.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = tempfile.c; path = ../cups/tempfile.c; sourceTree = "<group>"; };
72220EFB133305BB00FCA411 /* request.c */,
72220EFC133305BB00FCA411 /* sidechannel.c */,
72220EFF133305BB00FCA411 /* snmp.c */,
- 72220F00133305BB00FCA411 /* snprintf.c */,
72220F02133305BB00FCA411 /* string.c */,
72220F03133305BB00FCA411 /* tempfile.c */,
27F515452AAFBECF0045EE21 /* test-internal.h */,
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 */,
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 */,
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 */,
/*
* 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.
*
#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?
*/
/* #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?
*/