History

add hg and python

cinap_lenrek committed 15 years ago

Commit 4bb9e221 parent 987265c3706 files · +1228772 −-233Browse files

Showing the changes to sys/src/cmd/python/Python/mysnprintf.c (1 of 3706 files). Show all

Unified · Split

sys/src/cmd/python/Python/mysnprintf.c+93−0
@@ -0,0 +1,93 @@
1+#include "Python.h"
2+#include <ctype.h>
3+
4+/* snprintf() wrappers. If the platform has vsnprintf, we use it, else we
5+ emulate it in a half-hearted way. Even if the platform has it, we wrap
6+ it because platforms differ in what vsnprintf does in case the buffer
7+ is too small: C99 behavior is to return the number of characters that
8+ would have been written had the buffer not been too small, and to set
9+ the last byte of the buffer to \0. At least MS _vsnprintf returns a
10+ negative value instead, and fills the entire buffer with non-\0 data.
11+
12+ The wrappers ensure that str[size-1] is always \0 upon return.
13+
14+ PyOS_snprintf and PyOS_vsnprintf never write more than size bytes
15+ (including the trailing '\0') into str.
16+
17+ If the platform doesn't have vsnprintf, and the buffer size needed to
18+ avoid truncation exceeds size by more than 512, Python aborts with a
19+ Py_FatalError.
20+
21+ Return value (rv):
22+
23+ When 0 <= rv < size, the output conversion was unexceptional, and
24+ rv characters were written to str (excluding a trailing \0 byte at
25+ str[rv]).
26+
27+ When rv >= size, output conversion was truncated, and a buffer of
28+ size rv+1 would have been needed to avoid truncation. str[size-1]
29+ is \0 in this case.
30+
31+ When rv < 0, "something bad happened". str[size-1] is \0 in this
32+ case too, but the rest of str is unreliable. It could be that
33+ an error in format codes was detected by libc, or on platforms
34+ with a non-C99 vsnprintf simply that the buffer wasn't big enough
35+ to avoid truncation, or on platforms without any vsnprintf that
36+ PyMem_Malloc couldn't obtain space for a temp buffer.
37+
38+ CAUTION: Unlike C99, str != NULL and size > 0 are required.
39+*/
40+
41+int
42+PyOS_snprintf(char *str, size_t size, const char *format, ...)
43+{
44+ int rc;
45+ va_list va;
46+
47+ va_start(va, format);
48+ rc = PyOS_vsnprintf(str, size, format, va);
49+ va_end(va);
50+ return rc;
51+}
52+
53+int
54+PyOS_vsnprintf(char *str, size_t size, const char *format, va_list va)
55+{
56+ int len; /* # bytes written, excluding \0 */
57+#ifndef HAVE_SNPRINTF
58+ char *buffer;
59+#endif
60+ assert(str != NULL);
61+ assert(size > 0);
62+ assert(format != NULL);
63+
64+#ifdef HAVE_SNPRINTF
65+ len = vsnprintf(str, size, format, va);
66+#else
67+ /* Emulate it. */
68+ buffer = PyMem_MALLOC(size + 512);
69+ if (buffer == NULL) {
70+ len = -666;
71+ goto Done;
72+ }
73+
74+ len = vsprintf(buffer, format, va);
75+ if (len < 0)
76+ /* ignore the error */;
77+
78+ else if ((size_t)len >= size + 512)
79+ Py_FatalError("Buffer overflow in PyOS_snprintf/PyOS_vsnprintf");
80+
81+ else {
82+ const size_t to_copy = (size_t)len < size ?
83+ (size_t)len : size - 1;
84+ assert(to_copy < size);
85+ memcpy(str, buffer, to_copy);
86+ str[to_copy] = '\0';
87+ }
88+ PyMem_FREE(buffer);
89+Done:
90+#endif
91+ str[size-1] = '\0';
92+ return len;
93+}