GeezerVison is showing github.com — Let's get rid of sprintf() · Issue #101703 · python/cpython
Let's get rid of sprintf() #101703DescriptionOn macOS with Xcode 14 we now get warnings like these:
Objects/unicodeobject.c:736:16: warning: 'sprintf' is deprecated: This function is provided for compatibility reasons only. Due to security concerns inherent in the design of sprintf(3), it is highly recommended that you use snprintf(3) instead. [-Wdeprecated-declarations]
While we can prove to ourselves that these specific sprintf() calls are safe, the warnings are annoying, but disabling them would also disable other, more useful warnings (or so @Yhg1s tells me on Discord). So let's just switch these to snprintf().
Linked PRs
Reacted by Erlend E. Aasland, Oleg Iarygin, Furkan Onder, Christopher Chavez and Suraj Reacted by Erlend E. Aasland and Furkan Onder Activityterryjreedy commented on Feb 8, 2023 There are 49 hits in our .c code + some in externals. serhiy-storchaka commented on Feb 9, 2023 Interesting, there were issues with portability of snprintf (on Windows) in the past. I hope they were fixed in last 20 years. erlend-aasland commented on Feb 9, 2023
Interesting, there were issues with portability of snprintf (on Windows) in the past. I hope they were fixed in last 20 years.
CC. @eryksun eryksun commented on Feb 9, 2023 Supported builds of Python 3.5+ on Windows use Visual Studio 2015+ and the Universal C Runtime (UCRT), for which snprintf() and vsnprintf() conform to C99. In Python 3.9+, "Include/pyerrors.h" no longer defines these two functions as macros that call non-standard _snprintf() and _vsnprintf().
PyOS_vsnprintf() in "Python/mysnprintf.c" was apparently overlooked when "pyerrors.h" was updated. It should have been modified to always call vsnprintf(). Also, all PyOS_snprintf() and PyOS_vsnprintf() calls can be replaced with snprintf() and vsnprintf().
Reacted by Erlend E. Aasland and Suraj terryjreedy commented on Apr 24, 2023 I closed #103733 as duplicate of this. gvanrossum commented on Mar 19, 2024 @terryjreedy @sobolevn Can this be closed? I haven't seen those warnings in a while, though I see plenty of sprintf() calls in the code still. terryjreedy commented on Mar 20, 2024 sobolevn commented on Mar 20, 2024 I've tried to compile CPython with explicit -Wdeprecated-declarations set in PY_STDMODULE_CFLAGS and got no warnings. However, sprintf() is still widely used:
» ag 'sprintf\('
Misc/HISTORY
24555: the standard sprintf() and vsprintf() C lib APIs, these versions
33626:similar to sprintf() in C. The right argument is either a single
33627:value or a tuple of values. All features of Standard C sprintf() are
Python/flowgraph.c
276: sprintf(arg, "arg: %d ", i->i_oparg);
279: sprintf(arg, "target: %p [%d] ", i->i_target, i->i_oparg);
Python/pystrtod.c
1204: exp_len = sprintf(p, "%+.02d", exp);
Python/specialize.c
368: sprintf(buf, "%s%s.txt", dirname, hex_name);
Objects/typeobject.c
5591: sprintf(msg, "type_traverse() called on non-heap type '%.100s'",
Objects/unicodeobject.c
789: size = sprintf(str, "&#%d;", PyUnicode_READ(kind, data, i));
2596: sprintf(buffer, fmt, va_arg(*vargs, long)) :
2597: sprintf(buffer, fmt, va_arg(*vargs, unsigned long));
2601: sprintf(buffer, fmt, va_arg(*vargs, long long)) :
2602: sprintf(buffer, fmt, va_arg(*vargs, unsigned long long));
2606: sprintf(buffer, fmt, va_arg(*vargs, Py_ssize_t)) :
2607: sprintf(buffer, fmt, va_arg(*vargs, size_t));
2610: len = sprintf(buffer, fmt, va_arg(*vargs, ptrdiff_t));
2614: sprintf(buffer, fmt, va_arg(*vargs, intmax_t)) :
2615: sprintf(buffer, fmt, va_arg(*vargs, uintmax_t));
2619: sprintf(buffer, fmt, va_arg(*vargs, int)) :
2620: sprintf(buffer, fmt, va_arg(*vargs, unsigned int));
2672: len = sprintf(number, "%p", va_arg(*vargs, void*));
8358: sprintf(buffer, "&#%d;", (int)PyUnicode_READ_CHAR(unicode, collpos));
Objects/bytesobject.c
269: sprintf(buffer, "%ld", va_arg(vargs, long));
272: sprintf(buffer, "%zd", va_arg(vargs, Py_ssize_t));
275: sprintf(buffer, "%d", va_arg(vargs, int));
283: sprintf(buffer, "%lu", va_arg(vargs, unsigned long));
286: sprintf(buffer, "%zu", va_arg(vargs, size_t));
289: sprintf(buffer, "%u", va_arg(vargs, unsigned int));
296: sprintf(buffer, "%i", va_arg(vargs, int));
302: sprintf(buffer, "%x", va_arg(vargs, int));
328: sprintf(buffer, "%p", va_arg(vargs, void*));
564:/* fmt%(v1,v2,...) is roughly equivalent to sprintf(fmt, v1, v2, ...) */
Parser/string_parser.c
134: sprintf(p, "\\U%08x", chr);
Programs/_freeze_module.c
124: sprintf(filename, "<frozen %s>", name);
Modules/_testexternalinspection.c
234: sprintf(maps_file_path, "/proc/%d/maps", pid);
Modules/_pickle.c
2110: sprintf(pdata, "%c%ld\n", INT, val);
Modules/unicodedata.c
1329: sprintf(buffer, "CJK UNIFIED IDEOGRAPH-%X", code);
Modules/_testcapimodule.c
991: sprintf(buffer, "%s module: \"%s\" attribute: \"%s\"", \
Modules/getnameinfo.c
142: sprintf(numserv, "%d", ntohs(port));
Modules/_datetimemodule.c
1629: sprintf(freplacement, "%06d", TIME_GET_MICROSECOND(object));
1631: sprintf(freplacement, "%06d", DATE_GET_MICROSECOND(object));
1633: sprintf(freplacement, "%06d", 0);
Modules/_ctypes/stgdict.c
651: sprintf(buf, "%s:%s:", fieldfmt, fieldname);
Modules/_ctypes/_ctypes.c
398: sprintf(buf, "%zd,", shape[k]);
400: sprintf(buf, "%zd)", shape[k]);
2538: cp += sprintf(cp, "%x", Py_SAFE_DOWNCAST(index, Py_ssize_t, int));
2547: cp += sprintf(cp, ":%x", Py_SAFE_DOWNCAST(target->b_index, Py_ssize_t, int));
3269: sprintf(mangled_name, "_%s@%d", name, i*4);
4768: sprintf(name, "%.200s_Array_%Id",
4771: sprintf(name, "%.200s_Array_%ld",
Not sure why this warning is gone. erlend-aasland commented on Mar 20, 2024 Well, we risk that when the next version your toolchain of choice is updated, the warnings will reappear. IMO we might as well fix them. @sobolevn's PR was a good start, but only needed to be split in more manageable chunks. sobolevn commented on Mar 20, 2024 I can redo some parts of it, there were rather easy. I'll start with them today. sobolevn commented on Nov 12, 2026 Today I got this warning during CPython compilation:
Programs/_freeze_module.c:129:5: warning: 'sprintf' is deprecated: This function is provided for compatibility reasons only. Due to security concerns inherent in the design of sprintf(3), it is highly recommended that you use snprintf(3) instead. [-Wdeprecated-declarations]
129 | sprintf(filename, "<frozen %s>", name);
| ^
/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/usr/include/_stdio.h:278:1: note: 'sprintf' has been explicitly marked deprecated here
278 | __deprecated_msg("This function is provided for compatibility reasons only. Due to security concerns inherent in the design of sprintf(3), it is highly recommended that you use snprintf(3) instead.")
| ^
/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/usr/include/sys/cdefs.h:227:48: note: expanded from macro '__deprecated_msg'
227 | #define __deprecated_msg(_msg) __attribute__((__deprecated__(_msg)))
| ^
1 warning generated.
Since my last big PR never made it in, I propose splitting the work into simple small PRs that are easy to review / merge / backport.
MetadataMetadataDevelopmentNo branches or pull requestsIssue actions
|