~ubuntu-branches/ubuntu/natty/python3.1/natty-security

« back to all changes in this revision

Viewing changes to Python/mysnprintf.c

  • Committer: Bazaar Package Importer
  • Author(s): Matthias Klose
  • Date: 2010-07-06 16:52:42 UTC
  • mfrom: (1.2.1 upstream) (2.1.11 sid)
  • Revision ID: james.westby@ubuntu.com-20100706165242-2xv4i019r3et6c0j
Tags: 3.1.2+20100706-1ubuntu1
* Merge with Debian; remaining changes:
  - Regenerate the control file.
  - Add debian/patches/overwrite-semaphore-check for Lucid buildds.

Show diffs side-by-side

added added

removed removed

Lines of Context:
19
19
 
20
20
   Return value (rv):
21
21
 
22
 
        When 0 <= rv < size, the output conversion was unexceptional, and
23
 
        rv characters were written to str (excluding a trailing \0 byte at
24
 
        str[rv]).
25
 
 
26
 
        When rv >= size, output conversion was truncated, and a buffer of
27
 
        size rv+1 would have been needed to avoid truncation.  str[size-1]
28
 
        is \0 in this case.
29
 
 
30
 
        When rv < 0, "something bad happened".  str[size-1] is \0 in this
31
 
        case too, but the rest of str is unreliable.  It could be that
32
 
        an error in format codes was detected by libc, or on platforms
33
 
        with a non-C99 vsnprintf simply that the buffer wasn't big enough
34
 
        to avoid truncation, or on platforms without any vsnprintf that
35
 
        PyMem_Malloc couldn't obtain space for a temp buffer.
 
22
    When 0 <= rv < size, the output conversion was unexceptional, and
 
23
    rv characters were written to str (excluding a trailing \0 byte at
 
24
    str[rv]).
 
25
 
 
26
    When rv >= size, output conversion was truncated, and a buffer of
 
27
    size rv+1 would have been needed to avoid truncation.  str[size-1]
 
28
    is \0 in this case.
 
29
 
 
30
    When rv < 0, "something bad happened".  str[size-1] is \0 in this
 
31
    case too, but the rest of str is unreliable.  It could be that
 
32
    an error in format codes was detected by libc, or on platforms
 
33
    with a non-C99 vsnprintf simply that the buffer wasn't big enough
 
34
    to avoid truncation, or on platforms without any vsnprintf that
 
35
    PyMem_Malloc couldn't obtain space for a temp buffer.
36
36
 
37
37
   CAUTION:  Unlike C99, str != NULL and size > 0 are required.
38
38
*/
40
40
int
41
41
PyOS_snprintf(char *str, size_t size, const  char  *format, ...)
42
42
{
43
 
        int rc;
44
 
        va_list va;
 
43
    int rc;
 
44
    va_list va;
45
45
 
46
 
        va_start(va, format);
47
 
        rc = PyOS_vsnprintf(str, size, format, va);
48
 
        va_end(va);
49
 
        return rc;
 
46
    va_start(va, format);
 
47
    rc = PyOS_vsnprintf(str, size, format, va);
 
48
    va_end(va);
 
49
    return rc;
50
50
}
51
51
 
52
52
int
53
53
PyOS_vsnprintf(char *str, size_t size, const char  *format, va_list va)
54
54
{
55
 
        int len;  /* # bytes written, excluding \0 */
 
55
    int len;  /* # bytes written, excluding \0 */
56
56
#ifdef HAVE_SNPRINTF
57
57
#define _PyOS_vsnprintf_EXTRA_SPACE 1
58
58
#else
59
59
#define _PyOS_vsnprintf_EXTRA_SPACE 512
60
 
        char *buffer;
 
60
    char *buffer;
61
61
#endif
62
 
        assert(str != NULL);
63
 
        assert(size > 0);
64
 
        assert(format != NULL);
65
 
        /* We take a size_t as input but return an int.  Sanity check
66
 
         * our input so that it won't cause an overflow in the
67
 
         * vsnprintf return value or the buffer malloc size.  */
68
 
        if (size > INT_MAX - _PyOS_vsnprintf_EXTRA_SPACE) {
69
 
                len = -666;
70
 
                goto Done;
71
 
        }
 
62
    assert(str != NULL);
 
63
    assert(size > 0);
 
64
    assert(format != NULL);
 
65
    /* We take a size_t as input but return an int.  Sanity check
 
66
     * our input so that it won't cause an overflow in the
 
67
     * vsnprintf return value or the buffer malloc size.  */
 
68
    if (size > INT_MAX - _PyOS_vsnprintf_EXTRA_SPACE) {
 
69
        len = -666;
 
70
        goto Done;
 
71
    }
72
72
 
73
73
#ifdef HAVE_SNPRINTF
74
 
        len = vsnprintf(str, size, format, va);
 
74
    len = vsnprintf(str, size, format, va);
75
75
#else
76
 
        /* Emulate it. */
77
 
        buffer = PyMem_MALLOC(size + _PyOS_vsnprintf_EXTRA_SPACE);
78
 
        if (buffer == NULL) {
79
 
                len = -666;
80
 
                goto Done;
81
 
        }
82
 
 
83
 
        len = vsprintf(buffer, format, va);
84
 
        if (len < 0)
85
 
                /* ignore the error */;
86
 
 
87
 
        else if ((size_t)len >= size + _PyOS_vsnprintf_EXTRA_SPACE)
88
 
                Py_FatalError("Buffer overflow in PyOS_snprintf/PyOS_vsnprintf");
89
 
 
90
 
        else {
91
 
                const size_t to_copy = (size_t)len < size ?
92
 
                                        (size_t)len : size - 1;
93
 
                assert(to_copy < size);
94
 
                memcpy(str, buffer, to_copy);
95
 
                str[to_copy] = '\0';
96
 
        }
97
 
        PyMem_FREE(buffer);
 
76
    /* Emulate it. */
 
77
    buffer = PyMem_MALLOC(size + _PyOS_vsnprintf_EXTRA_SPACE);
 
78
    if (buffer == NULL) {
 
79
        len = -666;
 
80
        goto Done;
 
81
    }
 
82
 
 
83
    len = vsprintf(buffer, format, va);
 
84
    if (len < 0)
 
85
        /* ignore the error */;
 
86
 
 
87
    else if ((size_t)len >= size + _PyOS_vsnprintf_EXTRA_SPACE)
 
88
        Py_FatalError("Buffer overflow in PyOS_snprintf/PyOS_vsnprintf");
 
89
 
 
90
    else {
 
91
        const size_t to_copy = (size_t)len < size ?
 
92
                                (size_t)len : size - 1;
 
93
        assert(to_copy < size);
 
94
        memcpy(str, buffer, to_copy);
 
95
        str[to_copy] = '\0';
 
96
    }
 
97
    PyMem_FREE(buffer);
98
98
#endif
99
99
Done:
100
 
        if (size > 0)
101
 
                str[size-1] = '\0';
102
 
        return len;
 
100
    if (size > 0)
 
101
        str[size-1] = '\0';
 
102
    return len;
103
103
#undef _PyOS_vsnprintf_EXTRA_SPACE
104
104
}