zmc
2023-10-12 ed135d79df12a2466b52dae1a82326941211dcc9
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
U
O±dõ?ã@sddlZddlZddlZddlZddlZddlZddlZddlm    Z    m
Z
m Z ddl Z ej dd„ƒZdd„Zdd„Zd    d
„Zd d „Zd d„Zdd„Zdd„Zdd„Zdd„Zdd„Zejjdd„ƒZejje jjdkddej ddd dg¡d!d"„ƒƒZ d#d$„Z!dS)%éN)ÚextbuildÚ assert_warnsÚIS_WASMcCs|tj d¡rt d¡tr$t d¡dddddd    g}d
}d }zd d l}|WStk
r^YnXtj    d||t
  ¡g||dS)a Add a memory policy that returns a false pointer 64 bytes into the
    actual allocation, and fill the prefix with some text. Then check at each
    memory manipulation that the prefix exists, to make sure all alloc/realloc/
    free/calloc go via the functions here.
    Úcygwinzlink fails on cygwinzCan't build module inside Wasm)Úget_default_policyÚ METH_NOARGSzj
             Py_INCREF(PyDataMem_DefaultHandler);
             return PyDataMem_DefaultHandler;
         )Úset_secret_data_policyraM
             PyObject *secret_data =
                 PyCapsule_New(&secret_data_handler, "mem_handler", NULL);
             if (secret_data == NULL) {
                 return NULL;
             }
             PyObject *old = PyDataMem_SetHandler(secret_data);
             Py_DECREF(secret_data);
             return old;
         )Úset_old_policyÚMETH_Oa
             PyObject *old;
             if (args != NULL && PyCapsule_CheckExact(args)) {
                 old = PyDataMem_SetHandler(args);
             }
             else {
                 old = PyDataMem_SetHandler(NULL);
             }
             return old;
         )Ú    get_arrayraM
            char *buf = (char *)malloc(20);
            npy_intp dims[1];
            dims[0] = 20;
            PyArray_Descr *descr =  PyArray_DescrNewFromType(NPY_UINT8);
            return PyArray_NewFromDescr(&PyArray_Type, descr, 1, dims, NULL,
                                        buf, NPY_ARRAY_WRITEABLE, NULL);
         )Úset_ownr
aƒ
            if (!PyArray_Check(args)) {
                PyErr_SetString(PyExc_ValueError,
                             "need an ndarray");
                return NULL;
            }
            PyArray_ENABLEFLAGS((PyArrayObject*)args, NPY_ARRAY_OWNDATA);
            // Maybe try this too?
            // PyArray_BASE(PyArrayObject *)args) = NULL;
            Py_RETURN_NONE;
         )Úget_array_with_basera~
            char *buf = (char *)malloc(20);
            npy_intp dims[1];
            dims[0] = 20;
            PyArray_Descr *descr =  PyArray_DescrNewFromType(NPY_UINT8);
            PyObject *arr = PyArray_NewFromDescr(&PyArray_Type, descr, 1, dims,
                                                 NULL, buf,
                                                 NPY_ARRAY_WRITEABLE, NULL);
            if (arr == NULL) return NULL;
            PyObject *obj = PyCapsule_New(buf, "buf capsule",
                                          (PyCapsule_Destructor)&warn_on_free);
            if (obj == NULL) {
                Py_DECREF(arr);
                return NULL;
            }
            if (PyArray_SetBaseObject((PyArrayObject *)arr, obj) < 0) {
                Py_DECREF(arr);
                Py_DECREF(obj);
                return NULL;
            }
            return arr;
 
         a
        #define NPY_NO_DEPRECATED_API NPY_1_7_API_VERSION
        #include <numpy/arrayobject.h>
        /*
         * This struct allows the dynamic configuration of the allocator funcs
         * of the `secret_data_allocator`. It is provided here for
         * demonstration purposes, as a valid `ctx` use-case scenario.
         */
        typedef struct {
            void *(*malloc)(size_t);
            void *(*calloc)(size_t, size_t);
            void *(*realloc)(void *, size_t);
            void (*free)(void *);
        } SecretDataAllocatorFuncs;
 
        NPY_NO_EXPORT void *
        shift_alloc(void *ctx, size_t sz) {
            SecretDataAllocatorFuncs *funcs = (SecretDataAllocatorFuncs *)ctx;
            char *real = (char *)funcs->malloc(sz + 64);
            if (real == NULL) {
                return NULL;
            }
            snprintf(real, 64, "originally allocated %ld", (unsigned long)sz);
            return (void *)(real + 64);
        }
        NPY_NO_EXPORT void *
        shift_zero(void *ctx, size_t sz, size_t cnt) {
            SecretDataAllocatorFuncs *funcs = (SecretDataAllocatorFuncs *)ctx;
            char *real = (char *)funcs->calloc(sz + 64, cnt);
            if (real == NULL) {
                return NULL;
            }
            snprintf(real, 64, "originally allocated %ld via zero",
                     (unsigned long)sz);
            return (void *)(real + 64);
        }
        NPY_NO_EXPORT void
        shift_free(void *ctx, void * p, npy_uintp sz) {
            SecretDataAllocatorFuncs *funcs = (SecretDataAllocatorFuncs *)ctx;
            if (p == NULL) {
                return ;
            }
            char *real = (char *)p - 64;
            if (strncmp(real, "originally allocated", 20) != 0) {
                fprintf(stdout, "uh-oh, unmatched shift_free, "
                        "no appropriate prefix\n");
                /* Make C runtime crash by calling free on the wrong address */
                funcs->free((char *)p + 10);
                /* funcs->free(real); */
            }
            else {
                npy_uintp i = (npy_uintp)atoi(real +20);
                if (i != sz) {
                    fprintf(stderr, "uh-oh, unmatched shift_free"
                            "(ptr, %ld) but allocated %ld\n", sz, i);
                    /* This happens in some places, only print */
                    funcs->free(real);
                }
                else {
                    funcs->free(real);
                }
            }
        }
        NPY_NO_EXPORT void *
        shift_realloc(void *ctx, void * p, npy_uintp sz) {
            SecretDataAllocatorFuncs *funcs = (SecretDataAllocatorFuncs *)ctx;
            if (p != NULL) {
                char *real = (char *)p - 64;
                if (strncmp(real, "originally allocated", 20) != 0) {
                    fprintf(stdout, "uh-oh, unmatched shift_realloc\n");
                    return realloc(p, sz);
                }
                return (void *)((char *)funcs->realloc(real, sz + 64) + 64);
            }
            else {
                char *real = (char *)funcs->realloc(p, sz + 64);
                if (real == NULL) {
                    return NULL;
                }
                snprintf(real, 64, "originally allocated "
                         "%ld  via realloc", (unsigned long)sz);
                return (void *)(real + 64);
            }
        }
        /* As an example, we use the standard {m|c|re}alloc/free funcs. */
        static SecretDataAllocatorFuncs secret_data_handler_ctx = {
            malloc,
            calloc,
            realloc,
            free
        };
        static PyDataMem_Handler secret_data_handler = {
            "secret_data_allocator",
            1,
            {
                &secret_data_handler_ctx, /* ctx */
                shift_alloc,              /* malloc */
                shift_zero,               /* calloc */
                shift_realloc,            /* realloc */
                shift_free                /* free */
            }
        };
        void warn_on_free(void *capsule) {
            PyErr_WarnEx(PyExc_UserWarning, "in warn_on_free", 1);
            void * obj = PyCapsule_GetPointer(capsule,
                                              PyCapsule_GetName(capsule));
            free(obj);
        };
        zimport_array();rNÚ
mem_policy)ÚprologueÚ include_dirsÚ    build_dirÚ    more_init) ÚsysÚplatformÚ
startswithÚpytestÚskiprrÚ ImportErrorrZbuild_and_import_extensionÚnpZ get_include)Ztmp_pathZ    functionsrrr©rúWd:\z\workplace\vscode\pyvenv\venv\Lib\site-packages\numpy/core/tests/test_mem_policy.pyÚ
get_module s2 
 
 
 
 ÔDmûrcCs
tjjj}tjjj}|ƒ}t d¡ d¡}||ƒdks:t‚||ƒdksJt‚||jƒ|ks\t‚||jƒdksnt‚|     ¡}t d¡ d¡}||ƒdks–t‚||ƒdks¦t‚||jƒdks¸t‚||jƒdksÊt‚|dkrì| 
d¡|ƒdksêt‚n| 
|¡|ƒ|kst‚dS)Né
©éééÚsecret_data_allocatorÚdefault_allocator) rÚcoreÚ
multiarrayÚget_handler_nameÚget_handler_versionÚarangeÚreshapeÚAssertionErrorÚbaserr    )rr&r'Úorig_policy_nameÚaÚ orig_policyÚbrrrÚtest_set_policy×s&
 
 
 
r0cCsftjjj}| d¡}|ƒdks"t‚| d¡}|ƒdks:t‚| |¡}||kr\| ¡ksbnt‚dS©Nr#)rr$r%r&r    r*r)rr&r.Z def_policy_1Z def_policy_2rrrÚtest_default_policy_singletonós
 
 
 
r2cCs¨Gdd„dtjƒ}tjjj}|ƒ}t d¡ |¡ d¡}||ƒdksHt‚|j    j
dksXt‚||j ƒdksjt‚|j j    j
dks|t‚||j j ƒ|kst‚|j j j    j
dks¤t‚dS)Nc@s eZdZdS)z&test_policy_propagation.<locals>.MyArrN)Ú__name__Ú
__module__Ú __qualname__rrrrÚMyArr sr6rrFT) rZndarrayr$r%r&r(Úviewr)r*ÚflagsZowndatar+)rr6r&r,r-rrrÚtest_policy_propagations
r9cÃsP|dkr&| ¡tjj ¡dksDt‚n| d¡tjj ¡dksDt‚| ¡dS©Nr#r")rrr$r%r&r*r    Úset©rr,ÚeventrrrÚconcurrent_context1s 
r>cÃsj| ¡IdHtjj ¡|ks"t‚|dkrH| ¡tjj ¡dksft‚n| d¡tjj ¡dksft‚dSr:)Úwaitrr$r%r&r*rr    r<rrrÚconcurrent_context2%s
r@cÃsdtjj ¡}t ¡}t t|||ƒ¡}t t|||ƒ¡}|IdH|IdHtjj ¡|ks`t    ‚dS)N)
rr$r%r&ÚasyncioÚEventZ create_taskr>r@r*©rr,r=Zconcurrent_task1Zconcurrent_task2rrrÚasync_test_context_locality2s 
ÿ
ÿ
 
rDcCs:tjjdkr(tjdd…dkr(t d¡t t|ƒ¡dS)NÚpypyé)érFéz+no context-locality support in PyPy < 7.3.6)    rÚimplementationÚnameÚpypy_version_inforrrAÚrunrD)rrrrÚtest_context_localityBs
 ÿ
rMcCs(| ¡tjj ¡dkst‚| ¡dS)Nr")rrr$r%r&r*r;©rr=rrrÚconcurrent_thread1IsrOcCs(| ¡tjj ¡dkst‚| ¡dSr1)r?rr$r%r&r*rrNrrrÚconcurrent_thread2OsrPcCsptjj ¡}t ¡}tjt||fd}tjt||fd}|     ¡|     ¡| 
¡| 
¡tjj ¡|kslt ‚dS)N)ÚtargetÚargs) rr$r%r&Ú    threadingrBÚThreadrOrPÚstartÚjoinr*rCrrrÚtest_thread_localityWs ÿÿrWcCs¦t d¡}tjj |¡}| ¡}t d¡}tjj |¡dks@t‚|dkrxtjjdddgds`t‚tjjdddgdsxt‚|     |¡t d¡}tjj |¡|ks¢t‚dS)Nrr"r#Úfullrz-vv)ÚverboseZ
extra_argv)
rr(r$r%r&rr*ÚtestÚmar    )rr-r,r.r/ÚcrrrÚtest_new_policyis
 
 
 
r]rEz;bad interaction between getenv and os.environ inside pytest)ÚreasonÚpolicyÚ0Ú1c    CsÈ| ¡}tjj |¡dkst‚| |¡tj     dd¡}|dkrVdtjkr`tj 
d¡n
|tjd<z6|dkrŠt t ƒ}~t  ¡W5QRXn
~t  ¡W5|dkr¸dtjkrÂtj 
d¡n
|tjd<XdS)NZNUMPY_WARN_IF_NO_MEM_POLICYra)r rr$r%r&r*r ÚosÚenvironÚgetÚpoprÚRuntimeWarningÚgcÚcollect)rr_r-ZoldvalÚwrrrÚtest_switch_owner…s&
 
 
 
 
rjc    Cs0| ¡}tjtdd~t ¡W5QRXdS)NZ warn_on_free)Úmatch)r rZwarnsÚ UserWarningrgrh)rr-rrrÚtest_owner_is_base¥srm)"rArgrbrÚnumpyrrSÚwarningsZ numpy.testingrrrrZfixturerr0r2r9r>r@rDrMrOrPrWÚmarkZslowr]ZxfailrIrJZ parametrizerjrmrrrrÚ<module>s:
K
 
ÿ