##// END OF EJS Templates
base85: fix leak on error return from b85decode()...
Yuya Nishihara -
r39483:91477b12 stable
parent child Browse files
Show More
@@ -1,182 +1,191 b''
1 1 /*
2 2 base85 codec
3 3
4 4 Copyright 2006 Brendan Cully <brendan@kublai.com>
5 5
6 6 This software may be used and distributed according to the terms of
7 7 the GNU General Public License, incorporated herein by reference.
8 8
9 9 Largely based on git's implementation
10 10 */
11 11
12 12 #define PY_SSIZE_T_CLEAN
13 13 #include <Python.h>
14 14
15 15 #include "util.h"
16 16
17 17 static const char b85chars[] =
18 18 "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"
19 19 "abcdefghijklmnopqrstuvwxyz!#$%&()*+-;<=>?@^_`{|}~";
20 20 static char b85dec[256];
21 21
22 22 static void b85prep(void)
23 23 {
24 24 unsigned i;
25 25
26 26 memset(b85dec, 0, sizeof(b85dec));
27 27 for (i = 0; i < sizeof(b85chars); i++)
28 28 b85dec[(int)(b85chars[i])] = i + 1;
29 29 }
30 30
31 31 static PyObject *b85encode(PyObject *self, PyObject *args)
32 32 {
33 33 const unsigned char *text;
34 34 PyObject *out;
35 35 char *dst;
36 36 Py_ssize_t len, olen, i;
37 37 unsigned int acc, val, ch;
38 38 int pad = 0;
39 39
40 40 if (!PyArg_ParseTuple(args, PY23("s#|i", "y#|i"), &text, &len, &pad))
41 41 return NULL;
42 42
43 43 if (pad)
44 44 olen = ((len + 3) / 4 * 5) - 3;
45 45 else {
46 46 olen = len % 4;
47 47 if (olen)
48 48 olen++;
49 49 olen += len / 4 * 5;
50 50 }
51 51 if (!(out = PyBytes_FromStringAndSize(NULL, olen + 3)))
52 52 return NULL;
53 53
54 54 dst = PyBytes_AsString(out);
55 55
56 56 while (len) {
57 57 acc = 0;
58 58 for (i = 24; i >= 0; i -= 8) {
59 59 ch = *text++;
60 60 acc |= ch << i;
61 61 if (--len == 0)
62 62 break;
63 63 }
64 64 for (i = 4; i >= 0; i--) {
65 65 val = acc % 85;
66 66 acc /= 85;
67 67 dst[i] = b85chars[val];
68 68 }
69 69 dst += 5;
70 70 }
71 71
72 72 if (!pad)
73 73 _PyBytes_Resize(&out, olen);
74 74
75 75 return out;
76 76 }
77 77
78 78 static PyObject *b85decode(PyObject *self, PyObject *args)
79 79 {
80 PyObject *out;
80 PyObject *out = NULL;
81 81 const char *text;
82 82 char *dst;
83 83 Py_ssize_t len, i, j, olen, cap;
84 84 int c;
85 85 unsigned int acc;
86 86
87 87 if (!PyArg_ParseTuple(args, PY23("s#", "y#"), &text, &len))
88 88 return NULL;
89 89
90 90 olen = len / 5 * 4;
91 91 i = len % 5;
92 92 if (i)
93 93 olen += i - 1;
94 94 if (!(out = PyBytes_FromStringAndSize(NULL, olen)))
95 95 return NULL;
96 96
97 97 dst = PyBytes_AsString(out);
98 98
99 99 i = 0;
100 100 while (i < len) {
101 101 acc = 0;
102 102 cap = len - i - 1;
103 103 if (cap > 4)
104 104 cap = 4;
105 105 for (j = 0; j < cap; i++, j++) {
106 106 c = b85dec[(int)*text++] - 1;
107 if (c < 0)
108 return PyErr_Format(
107 if (c < 0) {
108 PyErr_Format(
109 109 PyExc_ValueError,
110 110 "bad base85 character at position %d",
111 111 (int)i);
112 goto bail;
113 }
112 114 acc = acc * 85 + c;
113 115 }
114 116 if (i++ < len) {
115 117 c = b85dec[(int)*text++] - 1;
116 if (c < 0)
117 return PyErr_Format(
118 if (c < 0) {
119 PyErr_Format(
118 120 PyExc_ValueError,
119 121 "bad base85 character at position %d",
120 122 (int)i);
123 goto bail;
124 }
121 125 /* overflow detection: 0xffffffff == "|NsC0",
122 126 * "|NsC" == 0x03030303 */
123 if (acc > 0x03030303 || (acc *= 85) > 0xffffffff - c)
124 return PyErr_Format(
127 if (acc > 0x03030303 || (acc *= 85) > 0xffffffff - c) {
128 PyErr_Format(
125 129 PyExc_ValueError,
126 130 "bad base85 sequence at position %d",
127 131 (int)i);
132 goto bail;
133 }
128 134 acc += c;
129 135 }
130 136
131 137 cap = olen < 4 ? olen : 4;
132 138 olen -= cap;
133 139 for (j = 0; j < 4 - cap; j++)
134 140 acc *= 85;
135 141 if (cap && cap < 4)
136 142 acc += 0xffffff >> (cap - 1) * 8;
137 143 for (j = 0; j < cap; j++) {
138 144 acc = (acc << 8) | (acc >> 24);
139 145 *dst++ = acc;
140 146 }
141 147 }
142 148
143 149 return out;
150 bail:
151 Py_XDECREF(out);
152 return NULL;
144 153 }
145 154
146 155 static char base85_doc[] = "Base85 Data Encoding";
147 156
148 157 static PyMethodDef methods[] = {
149 158 {"b85encode", b85encode, METH_VARARGS,
150 159 "Encode text in base85.\n\n"
151 160 "If the second parameter is true, pad the result to a multiple of "
152 161 "five characters.\n"},
153 162 {"b85decode", b85decode, METH_VARARGS, "Decode base85 text.\n"},
154 163 {NULL, NULL},
155 164 };
156 165
157 166 static const int version = 1;
158 167
159 168 #ifdef IS_PY3K
160 169 static struct PyModuleDef base85_module = {
161 170 PyModuleDef_HEAD_INIT, "base85", base85_doc, -1, methods,
162 171 };
163 172
164 173 PyMODINIT_FUNC PyInit_base85(void)
165 174 {
166 175 PyObject *m;
167 176 b85prep();
168 177
169 178 m = PyModule_Create(&base85_module);
170 179 PyModule_AddIntConstant(m, "version", version);
171 180 return m;
172 181 }
173 182 #else
174 183 PyMODINIT_FUNC initbase85(void)
175 184 {
176 185 PyObject *m;
177 186 m = Py_InitModule3("base85", methods, base85_doc);
178 187
179 188 b85prep();
180 189 PyModule_AddIntConstant(m, "version", version);
181 190 }
182 191 #endif
General Comments 0
You need to be logged in to leave comments. Login now