ยปCore Development>Code coverage>Modules/_decimal/libmpdec/memory.c

Python code coverage for Modules/_decimal/libmpdec/memory.c

#countcontent
1n/a/*
2n/a * Copyright (c) 2008-2016 Stefan Krah. All rights reserved.
3n/a *
4n/a * Redistribution and use in source and binary forms, with or without
5n/a * modification, are permitted provided that the following conditions
6n/a * are met:
7n/a *
8n/a * 1. Redistributions of source code must retain the above copyright
9n/a * notice, this list of conditions and the following disclaimer.
10n/a *
11n/a * 2. Redistributions in binary form must reproduce the above copyright
12n/a * notice, this list of conditions and the following disclaimer in the
13n/a * documentation and/or other materials provided with the distribution.
14n/a *
15n/a * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS "AS IS" AND
16n/a * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17n/a * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18n/a * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19n/a * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20n/a * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21n/a * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22n/a * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23n/a * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24n/a * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25n/a * SUCH DAMAGE.
26n/a */
27n/a
28n/a
29n/a#include "mpdecimal.h"
30n/a#include <stdio.h>
31n/a#include <stdlib.h>
32n/a#include "typearith.h"
33n/a#include "mpalloc.h"
34n/a
35n/a
36n/a#if defined(_MSC_VER)
37n/a #pragma warning(disable : 4232)
38n/a#endif
39n/a
40n/a
41n/a/* Guaranteed minimum allocation for a coefficient. May be changed once
42n/a at program start using mpd_setminalloc(). */
43n/ampd_ssize_t MPD_MINALLOC = MPD_MINALLOC_MIN;
44n/a
45n/a/* Custom allocation and free functions */
46n/avoid *(* mpd_mallocfunc)(size_t size) = malloc;
47n/avoid *(* mpd_reallocfunc)(void *ptr, size_t size) = realloc;
48n/avoid *(* mpd_callocfunc)(size_t nmemb, size_t size) = calloc;
49n/avoid (* mpd_free)(void *ptr) = free;
50n/a
51n/a
52n/a/* emulate calloc if it is not available */
53n/avoid *
54n/ampd_callocfunc_em(size_t nmemb, size_t size)
55n/a{
56n/a void *ptr;
57n/a size_t req;
58n/a mpd_size_t overflow;
59n/a
60n/a#if MPD_SIZE_MAX < SIZE_MAX
61n/a /* full_coverage test only */
62n/a if (nmemb > MPD_SIZE_MAX || size > MPD_SIZE_MAX) {
63n/a return NULL;
64n/a }
65n/a#endif
66n/a
67n/a req = mul_size_t_overflow((mpd_size_t)nmemb, (mpd_size_t)size,
68n/a &overflow);
69n/a if (overflow) {
70n/a return NULL;
71n/a }
72n/a
73n/a ptr = mpd_mallocfunc(req);
74n/a if (ptr == NULL) {
75n/a return NULL;
76n/a }
77n/a /* used on uint32_t or uint64_t */
78n/a memset(ptr, 0, req);
79n/a
80n/a return ptr;
81n/a}
82n/a
83n/a
84n/a/* malloc with overflow checking */
85n/avoid *
86n/ampd_alloc(mpd_size_t nmemb, mpd_size_t size)
87n/a{
88n/a mpd_size_t req, overflow;
89n/a
90n/a req = mul_size_t_overflow(nmemb, size, &overflow);
91n/a if (overflow) {
92n/a return NULL;
93n/a }
94n/a
95n/a return mpd_mallocfunc(req);
96n/a}
97n/a
98n/a/* calloc with overflow checking */
99n/avoid *
100n/ampd_calloc(mpd_size_t nmemb, mpd_size_t size)
101n/a{
102n/a mpd_size_t overflow;
103n/a
104n/a (void)mul_size_t_overflow(nmemb, size, &overflow);
105n/a if (overflow) {
106n/a return NULL;
107n/a }
108n/a
109n/a return mpd_callocfunc(nmemb, size);
110n/a}
111n/a
112n/a/* realloc with overflow checking */
113n/avoid *
114n/ampd_realloc(void *ptr, mpd_size_t nmemb, mpd_size_t size, uint8_t *err)
115n/a{
116n/a void *new;
117n/a mpd_size_t req, overflow;
118n/a
119n/a req = mul_size_t_overflow(nmemb, size, &overflow);
120n/a if (overflow) {
121n/a *err = 1;
122n/a return ptr;
123n/a }
124n/a
125n/a new = mpd_reallocfunc(ptr, req);
126n/a if (new == NULL) {
127n/a *err = 1;
128n/a return ptr;
129n/a }
130n/a
131n/a return new;
132n/a}
133n/a
134n/a/* struct hack malloc with overflow checking */
135n/avoid *
136n/ampd_sh_alloc(mpd_size_t struct_size, mpd_size_t nmemb, mpd_size_t size)
137n/a{
138n/a mpd_size_t req, overflow;
139n/a
140n/a req = mul_size_t_overflow(nmemb, size, &overflow);
141n/a if (overflow) {
142n/a return NULL;
143n/a }
144n/a
145n/a req = add_size_t_overflow(req, struct_size, &overflow);
146n/a if (overflow) {
147n/a return NULL;
148n/a }
149n/a
150n/a return mpd_mallocfunc(req);
151n/a}
152n/a
153n/a
154n/a/* Allocate a new decimal with a coefficient of length 'nwords'. In case
155n/a of an error the return value is NULL. */
156n/ampd_t *
157n/ampd_qnew_size(mpd_ssize_t nwords)
158n/a{
159n/a mpd_t *result;
160n/a
161n/a nwords = (nwords < MPD_MINALLOC) ? MPD_MINALLOC : nwords;
162n/a
163n/a result = mpd_alloc(1, sizeof *result);
164n/a if (result == NULL) {
165n/a return NULL;
166n/a }
167n/a
168n/a result->data = mpd_alloc(nwords, sizeof *result->data);
169n/a if (result->data == NULL) {
170n/a mpd_free(result);
171n/a return NULL;
172n/a }
173n/a
174n/a result->flags = 0;
175n/a result->exp = 0;
176n/a result->digits = 0;
177n/a result->len = 0;
178n/a result->alloc = nwords;
179n/a
180n/a return result;
181n/a}
182n/a
183n/a/* Allocate a new decimal with a coefficient of length MPD_MINALLOC.
184n/a In case of an error the return value is NULL. */
185n/ampd_t *
186n/ampd_qnew(void)
187n/a{
188n/a return mpd_qnew_size(MPD_MINALLOC);
189n/a}
190n/a
191n/a/* Allocate new decimal. Caller can check for NULL or MPD_Malloc_error.
192n/a Raises on error. */
193n/ampd_t *
194n/ampd_new(mpd_context_t *ctx)
195n/a{
196n/a mpd_t *result;
197n/a
198n/a result = mpd_qnew();
199n/a if (result == NULL) {
200n/a mpd_addstatus_raise(ctx, MPD_Malloc_error);
201n/a }
202n/a return result;
203n/a}
204n/a
205n/a/*
206n/a * Input: 'result' is a static mpd_t with a static coefficient.
207n/a * Assumption: 'nwords' >= result->alloc.
208n/a *
209n/a * Resize the static coefficient to a larger dynamic one and copy the
210n/a * existing data. If successful, the value of 'result' is unchanged.
211n/a * Otherwise, set 'result' to NaN and update 'status' with MPD_Malloc_error.
212n/a */
213n/aint
214n/ampd_switch_to_dyn(mpd_t *result, mpd_ssize_t nwords, uint32_t *status)
215n/a{
216n/a mpd_uint_t *p = result->data;
217n/a
218n/a assert(nwords >= result->alloc);
219n/a
220n/a result->data = mpd_alloc(nwords, sizeof *result->data);
221n/a if (result->data == NULL) {
222n/a result->data = p;
223n/a mpd_set_qnan(result);
224n/a mpd_set_positive(result);
225n/a result->exp = result->digits = result->len = 0;
226n/a *status |= MPD_Malloc_error;
227n/a return 0;
228n/a }
229n/a
230n/a memcpy(result->data, p, result->alloc * (sizeof *result->data));
231n/a result->alloc = nwords;
232n/a mpd_set_dynamic_data(result);
233n/a return 1;
234n/a}
235n/a
236n/a/*
237n/a * Input: 'result' is a static mpd_t with a static coefficient.
238n/a *
239n/a * Convert the coefficient to a dynamic one that is initialized to zero. If
240n/a * malloc fails, set 'result' to NaN and update 'status' with MPD_Malloc_error.
241n/a */
242n/aint
243n/ampd_switch_to_dyn_zero(mpd_t *result, mpd_ssize_t nwords, uint32_t *status)
244n/a{
245n/a mpd_uint_t *p = result->data;
246n/a
247n/a result->data = mpd_calloc(nwords, sizeof *result->data);
248n/a if (result->data == NULL) {
249n/a result->data = p;
250n/a mpd_set_qnan(result);
251n/a mpd_set_positive(result);
252n/a result->exp = result->digits = result->len = 0;
253n/a *status |= MPD_Malloc_error;
254n/a return 0;
255n/a }
256n/a
257n/a result->alloc = nwords;
258n/a mpd_set_dynamic_data(result);
259n/a
260n/a return 1;
261n/a}
262n/a
263n/a/*
264n/a * Input: 'result' is a static or a dynamic mpd_t with a dynamic coefficient.
265n/a * Resize the coefficient to length 'nwords':
266n/a * Case nwords > result->alloc:
267n/a * If realloc is successful:
268n/a * 'result' has a larger coefficient but the same value. Return 1.
269n/a * Otherwise:
270n/a * Set 'result' to NaN, update status with MPD_Malloc_error and return 0.
271n/a * Case nwords < result->alloc:
272n/a * If realloc is successful:
273n/a * 'result' has a smaller coefficient. result->len is undefined. Return 1.
274n/a * Otherwise (unlikely):
275n/a * 'result' is unchanged. Reuse the now oversized coefficient. Return 1.
276n/a */
277n/aint
278n/ampd_realloc_dyn(mpd_t *result, mpd_ssize_t nwords, uint32_t *status)
279n/a{
280n/a uint8_t err = 0;
281n/a
282n/a result->data = mpd_realloc(result->data, nwords, sizeof *result->data, &err);
283n/a if (!err) {
284n/a result->alloc = nwords;
285n/a }
286n/a else if (nwords > result->alloc) {
287n/a mpd_set_qnan(result);
288n/a mpd_set_positive(result);
289n/a result->exp = result->digits = result->len = 0;
290n/a *status |= MPD_Malloc_error;
291n/a return 0;
292n/a }
293n/a
294n/a return 1;
295n/a}
296n/a
297n/a