Skip to content

Commit 51db898

Browse files
committed
clean up error handling in string allocation functions
1 parent 7c5bcbb commit 51db898

File tree

5 files changed

+40
-52
lines changed

5 files changed

+40
-52
lines changed

stringdtype/stringdtype/src/casts.c

Lines changed: 20 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -207,7 +207,8 @@ unicode_to_string(PyArrayMethod_Context *context, char *const data[],
207207
npy_packed_static_string *out_pss = (npy_packed_static_string *)out;
208208
npy_string_free(out_pss);
209209
if (npy_string_newemptysize(out_num_bytes, out_pss) < 0) {
210-
gil_error(PyExc_MemoryError, "npy_string_newemptysize failed");
210+
gil_error(PyExc_MemoryError,
211+
"Failed to allocate string in unicode to string cast");
211212
return -1;
212213
}
213214
npy_static_string out_ss = {0, NULL};
@@ -481,23 +482,28 @@ bool_to_string(PyArrayMethod_Context *NPY_UNUSED(context), char *const data[],
481482
while (N--) {
482483
npy_packed_static_string *out_pss = (npy_packed_static_string *)out;
483484
npy_string_free(out_pss);
485+
char *ret_val = NULL;
486+
size_t size = 0;
484487
if ((npy_bool)(*in) == 1) {
485-
if (npy_string_newsize("True", 4, out_pss) < 0) {
486-
gil_error(PyExc_MemoryError, "npy_string_newsize failed");
487-
return -1;
488-
}
488+
ret_val = "True";
489+
size = 4;
489490
}
490491
else if ((npy_bool)(*in) == 0) {
491-
if (npy_string_newsize("False", 5, out_pss) < 0) {
492-
gil_error(PyExc_MemoryError, "npy_string_newsize failed");
493-
return -1;
494-
}
492+
ret_val = "False";
493+
size = 5;
495494
}
496495
else {
497496
gil_error(PyExc_RuntimeError,
498497
"invalid value encountered in bool to string cast");
499498
return -1;
500499
}
500+
if (npy_string_newsize(ret_val, size, out_pss) < 0) {
501+
// execution should never get here because this will be a small
502+
// string on all platforms
503+
gil_error(PyExc_MemoryError,
504+
"Failed to allocate string in bool to string cast");
505+
return -1;
506+
}
501507
in += in_stride;
502508
out += out_stride;
503509
}
@@ -593,7 +599,9 @@ pyobj_to_string(PyObject *obj, char *out)
593599
npy_packed_static_string *out_ss = (npy_packed_static_string *)out;
594600
npy_string_free(out_ss);
595601
if (npy_string_newsize(cstr_val, length, out_ss) < 0) {
596-
PyErr_SetString(PyExc_MemoryError, "npy_string_newsize failed");
602+
PyErr_SetString(PyExc_MemoryError,
603+
"Failed to allocate numpy string when converting from "
604+
"python string.");
597605
Py_DECREF(pystr_val);
598606
return -1;
599607
}
@@ -1087,7 +1095,8 @@ datetime_to_string(PyArrayMethod_Context *context, char *const data[],
10871095
if (npy_string_newsize(datetime_buf, strlen(datetime_buf),
10881096
out_pss) < 0) {
10891097
PyErr_SetString(PyExc_MemoryError,
1090-
"npy_string_newsize failed");
1098+
"Failed to allocate string when converting "
1099+
"from a datetime.");
10911100
return -1;
10921101
}
10931102
}

stringdtype/stringdtype/src/dtype.c

Lines changed: 5 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -31,19 +31,12 @@ new_stringdtype_instance(PyObject *na_object, int coerce)
3131
has_string_na = 1;
3232
Py_ssize_t size = 0;
3333
const char *buf = PyUnicode_AsUTF8AndSize(na_object, &size);
34-
int res = npy_string_newsize(buf, (size_t)size,
35-
&packed_default_string);
36-
if (res == -1) {
34+
if (npy_string_newsize(buf, (size_t)size, &packed_default_string) <
35+
0) {
3736
PyErr_NoMemory();
3837
Py_DECREF(new);
3938
return NULL;
4039
}
41-
else if (res == -2) {
42-
// this should never happen
43-
assert(0);
44-
Py_DECREF(new);
45-
return NULL;
46-
}
4740
}
4841
else {
4942
// treat as nan-like if != comparison returns a object whose truth
@@ -72,17 +65,10 @@ new_stringdtype_instance(PyObject *na_object, int coerce)
7265

7366
Py_ssize_t size = 0;
7467
const char *utf8_ptr = PyUnicode_AsUTF8AndSize(na_pystr, &size);
75-
// discard const to initialize buffer
76-
int res = npy_string_newsize(utf8_ptr, (size_t)size, &packed_na_name);
77-
if (res == -1) {
68+
if (npy_string_newsize(utf8_ptr, (size_t)size, &packed_na_name)) {
7869
PyErr_NoMemory();
7970
Py_DECREF(new);
80-
return NULL;
81-
}
82-
else if (res == -2) {
83-
// this should never happen
84-
assert(0);
85-
Py_DECREF(new);
71+
Py_DECREF(na_pystr);
8672
return NULL;
8773
}
8874
Py_DECREF(na_pystr);
@@ -235,19 +221,11 @@ stringdtype_setitem(StringDTypeObject *descr, PyObject *obj, char **dataptr)
235221
return -1;
236222
}
237223

238-
int res = npy_string_newsize(val, length, sdata);
239-
240-
if (res == -1) {
224+
if (npy_string_newsize(val, length, sdata) < 0) {
241225
PyErr_NoMemory();
242226
Py_DECREF(val_obj);
243227
return -1;
244228
}
245-
else if (res == -2) {
246-
// this should never happen
247-
assert(0);
248-
Py_DECREF(val_obj);
249-
return -1;
250-
}
251229
}
252230

253231
return 0;

stringdtype/stringdtype/src/static_string.c

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -118,10 +118,6 @@ int
118118
npy_string_newsize(const char *init, size_t size,
119119
npy_packed_static_string *to_init)
120120
{
121-
if (to_init == NULL || size > NPY_MAX_STRING_SIZE) {
122-
return -2;
123-
}
124-
125121
if (size == 0) {
126122
*to_init = *NPY_EMPTY_STRING;
127123
return 0;
@@ -157,10 +153,6 @@ npy_string_newsize(const char *init, size_t size,
157153
int
158154
npy_string_newemptysize(size_t size, npy_packed_static_string *out)
159155
{
160-
if (out == NULL || size > NPY_MAX_STRING_SIZE) {
161-
return -2;
162-
}
163-
164156
if (size == 0) {
165157
*out = *NPY_EMPTY_STRING;
166158
return 0;

stringdtype/stringdtype/src/static_string.h

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -25,9 +25,12 @@ extern const npy_packed_static_string *NPY_NULL_STRING;
2525
// calling this function, filling the newly allocated buffer with the copied
2626
// contents of the first *size* entries in *init*, which must be valid and
2727
// initialized beforehand. Calling npy_string_free on *to_init* before calling
28-
// this function on an existing string is sufficient to initialize it. Returns
29-
// -1 if malloc fails and -2 if the internal buffer in *to_init* is not NULL
30-
// to indicate a programming error. Returns 0 on success.
28+
// this function on an existing string or copying the contents of
29+
// NPY_EMPTY_STRING into *to_init* is sufficient to initialize it. Does not
30+
// check if *to_init* is NULL or if the internal buffer is non-NULL, undefined
31+
// behavior or memory leaks are possible if this function is passed a pointer
32+
// to a an unintialized struct, a NULL pointer, or an existing heap-allocated
33+
// string. Returns -1 if malloc fails. Returns 0 on success.
3134
int
3235
npy_string_newsize(const char *init, size_t size,
3336
npy_packed_static_string *to_init);
@@ -47,8 +50,14 @@ npy_string_dup(const npy_packed_static_string *in,
4750

4851
// Allocates a new string buffer for *out* with enough capacity to store
4952
// *size* bytes of text. Does not do any initialization, the caller must
50-
// initialize the string buffer. Returns -1 if malloc fails and -2 if *out* is
51-
// not NULL. Returns 0 on success.
53+
// initialize the string buffer after this function returns. Calling
54+
// npy_string_free on *to_init* before calling this function on an existing
55+
// string or copying the contents of NPY_EMPTY_STRING into *to_init* is
56+
// sufficient to initialize it.Does not check if *to_init* is NULL or if the
57+
// internal buffer is non-NULL, undefined behavior or memory leaks are
58+
// possible if this function is passed a pointer to a an unintialized struct,
59+
// a NULL pointer, or an existing heap-allocated string. Returns 0 on
60+
// success. Returns -1 if malloc fails. Returns 0 on success.
5261
int
5362
npy_string_newemptysize(size_t size, npy_packed_static_string *out);
5463

stringdtype/stringdtype/src/umath.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,7 @@ multiply_resolve_descriptors(
7373
\
7474
if (npy_string_newemptysize(newsize, ops) < 0) { \
7575
gil_error(PyExc_MemoryError, \
76-
"npy_string_newemptysize failed"); \
76+
"Failed to allocate string in string mutiply"); \
7777
return -1; \
7878
} \
7979
\

0 commit comments

Comments
 (0)