~jtaylor/ubuntu/precise/python-numpy/multiarch-fix-818867

« back to all changes in this revision

Viewing changes to numpy/core/src/multiarray/hashdescr.c

  • Committer: Bazaar Package Importer
  • Author(s): Sandro Tosi
  • Date: 2010-10-07 10:19:13 UTC
  • mfrom: (7.1.5 sid)
  • Revision ID: james.westby@ubuntu.com-20101007101913-8b1kmt8ho4upcl9s
Tags: 1:1.4.1-5
* debian/patches/10_use_local_python.org_object.inv_sphinx.diff
  - fixed small typo in description
* debian/patches/changeset_r8364.diff
  - fix memory corruption (double free); thanks to Joseph Barillari for the
    report and to Michael Gilbert for pushing resolution; Closes: #581058

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
#define PY_SSIZE_T_CLEAN
 
2
#include <Python.h>
 
3
#define _MULTIARRAYMODULE
 
4
#include <numpy/ndarrayobject.h>
 
5
 
 
6
#include "npy_config.h"
 
7
 
 
8
#include "hashdescr.h"
 
9
 
 
10
/*
 
11
 * How does this work ? The hash is computed from a list which contains all the
 
12
 * information specific to a type. The hard work is to build the list
 
13
 * (_array_descr_walk). The list is built as follows:
 
14
 *      * If the dtype is builtin (no fields, no subarray), then the list
 
15
 *      contains 6 items which uniquely define one dtype (_array_descr_builtin)
 
16
 *      * If the dtype is a compound array, one walk on each field. For each
 
17
 *      field, we append title, names, offset to the final list used for
 
18
 *      hashing, and then append the list recursively built for each
 
19
 *      corresponding dtype (_array_descr_walk_fields)
 
20
 *      * If the dtype is a subarray, one adds the shape tuple to the list, and
 
21
 *      then append the list recursively built for each corresponding dtype
 
22
 *      (_array_descr_walk_subarray)
 
23
 *
 
24
 */
 
25
 
 
26
static int _is_array_descr_builtin(PyArray_Descr* descr);
 
27
static int _array_descr_walk(PyArray_Descr* descr, PyObject *l);
 
28
static int _array_descr_walk_fields(PyObject* fields, PyObject* l);
 
29
static int _array_descr_builtin(PyArray_Descr* descr, PyObject *l);
 
30
 
 
31
/*
 
32
 * Return true if descr is a builtin type
 
33
 */
 
34
static int _is_array_descr_builtin(PyArray_Descr* descr)
 
35
{
 
36
        if (descr->fields != NULL && descr->fields != Py_None) {
 
37
                return 0;
 
38
        }
 
39
        if (descr->subarray != NULL) {
 
40
                return 0;
 
41
        }
 
42
        return 1;
 
43
}
 
44
 
 
45
/*
 
46
 * Add to l all the items which uniquely define a builtin type
 
47
 */
 
48
static int _array_descr_builtin(PyArray_Descr* descr, PyObject *l)
 
49
{
 
50
    Py_ssize_t i;
 
51
    PyObject *t, *item;
 
52
 
 
53
    /*
 
54
     * For builtin type, hash relies on : kind + byteorder + hasobject +
 
55
     * type_num + elsize + alignment
 
56
     */
 
57
    t = Py_BuildValue("(ccciii)", descr->kind, descr->byteorder,
 
58
            descr->hasobject, descr->type_num, descr->elsize,
 
59
            descr->alignment);
 
60
 
 
61
    for(i = 0; i < PyTuple_Size(t); ++i) {
 
62
        item = PyTuple_GetItem(t, i);
 
63
        if (item == NULL) {
 
64
            PyErr_SetString(PyExc_SystemError,
 
65
                    "(Hash) Error while computing builting hash");
 
66
            goto clean_t;
 
67
        }
 
68
        Py_INCREF(item);
 
69
        PyList_Append(l, item);
 
70
    }
 
71
 
 
72
    Py_DECREF(t);
 
73
    return 0;
 
74
 
 
75
clean_t:
 
76
    Py_DECREF(t);
 
77
    return -1;
 
78
}
 
79
 
 
80
/*
 
81
 * Walk inside the fields and add every item which will be used for hashing
 
82
 * into the list l
 
83
 *
 
84
 * Return 0 on success
 
85
 */
 
86
static int _array_descr_walk_fields(PyObject* fields, PyObject* l)
 
87
{
 
88
    PyObject *key, *value, *foffset, *fdescr;
 
89
    Py_ssize_t pos = 0;
 
90
    int st;
 
91
 
 
92
    while (PyDict_Next(fields, &pos, &key, &value)) {
 
93
        /*
 
94
         * For each field, add the key + descr + offset to l
 
95
         */
 
96
 
 
97
        /* XXX: are those checks necessary ? */
 
98
        if (!PyString_Check(key)) {
 
99
            PyErr_SetString(PyExc_SystemError,
 
100
                    "(Hash) key of dtype dict not a string ???");
 
101
            return -1;
 
102
        }
 
103
        if (!PyTuple_Check(value)) {
 
104
            PyErr_SetString(PyExc_SystemError,
 
105
                    "(Hash) value of dtype dict not a dtype ???");
 
106
            return -1;
 
107
        }
 
108
        if (PyTuple_Size(value) < 2) {
 
109
            PyErr_SetString(PyExc_SystemError,
 
110
                    "(Hash) Less than 2 items in dtype dict ???");
 
111
            return -1;
 
112
        }
 
113
        Py_INCREF(key);
 
114
        PyList_Append(l, key);
 
115
 
 
116
        fdescr = PyTuple_GetItem(value, 0);
 
117
        if (!PyArray_DescrCheck(fdescr)) {
 
118
            PyErr_SetString(PyExc_SystemError,
 
119
                    "(Hash) First item in compound dtype tuple not a descr ???");
 
120
            return -1;
 
121
        } else {
 
122
            Py_INCREF(fdescr);
 
123
            st = _array_descr_walk((PyArray_Descr*)fdescr, l);
 
124
            Py_DECREF(fdescr);
 
125
            if (st) {
 
126
                return -1;
 
127
            }
 
128
        }
 
129
 
 
130
        foffset = PyTuple_GetItem(value, 1);
 
131
        if (!PyInt_Check(foffset)) {
 
132
            PyErr_SetString(PyExc_SystemError,
 
133
                    "(Hash) Second item in compound dtype tuple not an int ???");
 
134
            return -1;
 
135
        } else {
 
136
            Py_INCREF(foffset);
 
137
            PyList_Append(l, foffset);
 
138
        }
 
139
    }
 
140
 
 
141
    return 0;
 
142
}
 
143
 
 
144
/*
 
145
 * Walk into subarray, and add items for hashing in l
 
146
 *
 
147
 * Return 0 on success
 
148
 */
 
149
static int _array_descr_walk_subarray(PyArray_ArrayDescr* adescr, PyObject *l)
 
150
{
 
151
    PyObject *item;
 
152
    Py_ssize_t i;
 
153
    int st;
 
154
 
 
155
    /*
 
156
     * Add shape and descr itself to the list of object to hash
 
157
     */
 
158
    if (PyTuple_Check(adescr->shape)) {
 
159
        for(i = 0; i < PyTuple_Size(adescr->shape); ++i) {
 
160
            item = PyTuple_GetItem(adescr->shape, i);
 
161
            if (item == NULL) {
 
162
                PyErr_SetString(PyExc_SystemError,
 
163
                        "(Hash) Error while getting shape item of subarray dtype ???");
 
164
                return -1;
 
165
            }
 
166
            Py_INCREF(item);
 
167
            PyList_Append(l, item);
 
168
        }
 
169
    } else if (PyInt_Check(adescr->shape)) {
 
170
        Py_INCREF(adescr->shape);
 
171
        PyList_Append(l, adescr->shape);
 
172
    } else {
 
173
        PyErr_SetString(PyExc_SystemError,
 
174
                "(Hash) Shape of subarray dtype neither a tuple or int ???");
 
175
        return -1;
 
176
    }
 
177
 
 
178
    Py_INCREF(adescr->base);
 
179
    st = _array_descr_walk(adescr->base, l);
 
180
    Py_DECREF(adescr->base);
 
181
 
 
182
    return st;
 
183
}
 
184
 
 
185
/*
 
186
 * 'Root' function to walk into a dtype. May be called recursively
 
187
 */
 
188
static int _array_descr_walk(PyArray_Descr* descr, PyObject *l)
 
189
{
 
190
    int st;
 
191
 
 
192
    if (_is_array_descr_builtin(descr)) {
 
193
        return _array_descr_builtin(descr, l);
 
194
    } else {
 
195
        if(descr->fields != NULL && descr->fields != Py_None) {
 
196
            if (!PyDict_Check(descr->fields)) {
 
197
                PyErr_SetString(PyExc_SystemError,
 
198
                        "(Hash) fields is not a dict ???");
 
199
                return -1;
 
200
            }
 
201
            st = _array_descr_walk_fields(descr->fields, l);
 
202
            if (st) {
 
203
                return -1;
 
204
            }
 
205
        }
 
206
        if(descr->subarray != NULL) {
 
207
            st = _array_descr_walk_subarray(descr->subarray, l);
 
208
            if (st) {
 
209
                return -1;
 
210
            }
 
211
        }
 
212
    }
 
213
 
 
214
    return 0;
 
215
}
 
216
 
 
217
/*
 
218
 * Return 0 if successfull
 
219
 */
 
220
static int _PyArray_DescrHashImp(PyArray_Descr *descr, long *hash)
 
221
{
 
222
    PyObject *l, *tl, *item;
 
223
    Py_ssize_t i;
 
224
    int st;
 
225
 
 
226
    l = PyList_New(0);
 
227
    if (l == NULL) {
 
228
        return -1;
 
229
    }
 
230
 
 
231
    st = _array_descr_walk(descr, l);
 
232
    if (st) {
 
233
        goto clean_l;
 
234
    }
 
235
 
 
236
    /*
 
237
     * Convert the list to tuple and compute the tuple hash using python
 
238
     * builtin function
 
239
     */
 
240
    tl = PyTuple_New(PyList_Size(l));
 
241
    for(i = 0; i < PyList_Size(l); ++i) {
 
242
        item = PyList_GetItem(l, i);
 
243
        if (item == NULL) {
 
244
            PyErr_SetString(PyExc_SystemError,
 
245
                    "(Hash) Error while translating the list into a tuple " \
 
246
                    "(NULL item)");
 
247
            goto clean_tl;
 
248
        }
 
249
        PyTuple_SetItem(tl, i, item);
 
250
    }
 
251
 
 
252
    *hash = PyObject_Hash(tl);
 
253
    if (*hash == -1) {
 
254
        /* XXX: does PyObject_Hash set an exception on failure ? */
 
255
#if 0
 
256
        PyErr_SetString(PyExc_SystemError,
 
257
                "(Hash) Error while hashing final tuple");
 
258
#endif
 
259
        goto clean_tl;
 
260
    }
 
261
    Py_DECREF(tl);
 
262
    Py_DECREF(l);
 
263
 
 
264
    return 0;
 
265
 
 
266
clean_tl:
 
267
    Py_DECREF(tl);
 
268
clean_l:
 
269
    Py_DECREF(l);
 
270
    return -1;
 
271
}
 
272
 
 
273
NPY_NO_EXPORT long
 
274
PyArray_DescrHash(PyObject* odescr)
 
275
{
 
276
    PyArray_Descr *descr;
 
277
    int st;
 
278
    long hash;
 
279
 
 
280
    if (!PyArray_DescrCheck(odescr)) {
 
281
        PyErr_SetString(PyExc_ValueError,
 
282
                "PyArray_DescrHash argument must be a type descriptor");
 
283
        return -1;
 
284
    }
 
285
    descr = (PyArray_Descr*)odescr;
 
286
 
 
287
    st = _PyArray_DescrHashImp(descr, &hash);
 
288
    if (st) {
 
289
        return -1;
 
290
    }
 
291
 
 
292
    return hash;
 
293
}