1 /*
2 ** SPDX-License-Identifier: BSD-3-Clause
3 ** Copyright Contributors to the OpenEXR Project.
4 */
5 
6 #include "internal_attr.h"
7 
8 #include "internal_constants.h"
9 #include "internal_structs.h"
10 
11 #include <string.h>
12 
13 /**************************************/
14 
15 int
exr_attr_opaquedata_init(exr_context_t ctxt,exr_attr_opaquedata_t * u,size_t b)16 exr_attr_opaquedata_init (
17     exr_context_t ctxt, exr_attr_opaquedata_t* u, size_t b)
18 {
19     exr_attr_opaquedata_t nil = { 0 };
20 
21     INTERN_EXR_PROMOTE_CONTEXT_OR_ERROR (ctxt);
22 
23     if (!u)
24         return pctxt->report_error (
25             pctxt,
26             EXR_ERR_INVALID_ARGUMENT,
27             "Invalid reference to opaque data object to initialize");
28 
29     if (b > (size_t) INT32_MAX)
30         return pctxt->print_error (
31             pctxt,
32             EXR_ERR_INVALID_ARGUMENT,
33             "Invalid size for opaque data (%" PRIu64
34             " bytes, must be <= INT32_MAX)",
35             (uint64_t) b);
36 
37     *u = nil;
38     if (b > 0)
39     {
40 
41         u->packed_data = pctxt->alloc_fn (b);
42         if (!u->packed_data)
43             return pctxt->standard_error (pctxt, EXR_ERR_OUT_OF_MEMORY);
44     }
45     u->size              = (int32_t) b;
46     u->packed_alloc_size = (int32_t) b;
47     return EXR_ERR_SUCCESS;
48 }
49 
50 /**************************************/
51 
52 exr_result_t
exr_attr_opaquedata_create(exr_context_t ctxt,exr_attr_opaquedata_t * u,size_t b,const void * d)53 exr_attr_opaquedata_create (
54     exr_context_t ctxt, exr_attr_opaquedata_t* u, size_t b, const void* d)
55 {
56     exr_result_t rv = exr_attr_opaquedata_init (ctxt, u, b);
57     if (rv == EXR_ERR_SUCCESS)
58     {
59         if (d) memcpy ((void*) u->packed_data, d, b);
60     }
61 
62     return rv;
63 }
64 
65 /**************************************/
66 
67 exr_result_t
exr_attr_opaquedata_destroy(exr_context_t ctxt,exr_attr_opaquedata_t * ud)68 exr_attr_opaquedata_destroy (exr_context_t ctxt, exr_attr_opaquedata_t* ud)
69 {
70     INTERN_EXR_PROMOTE_CONTEXT_OR_ERROR (ctxt);
71 
72     if (ud)
73     {
74         exr_attr_opaquedata_t nil = { 0 };
75         if (ud->packed_data && ud->packed_alloc_size > 0)
76             pctxt->free_fn (ud->packed_data);
77 
78         if (ud->unpacked_data && ud->destroy_unpacked_func_ptr)
79             ud->destroy_unpacked_func_ptr (
80                 ctxt, ud->unpacked_data, ud->unpacked_size);
81         *ud = nil;
82     }
83     return EXR_ERR_SUCCESS;
84 }
85 
86 /**************************************/
87 
88 exr_result_t
exr_attr_opaquedata_copy(exr_context_t ctxt,exr_attr_opaquedata_t * ud,const exr_attr_opaquedata_t * srcud)89 exr_attr_opaquedata_copy (
90     exr_context_t                ctxt,
91     exr_attr_opaquedata_t*       ud,
92     const exr_attr_opaquedata_t* srcud)
93 {
94     exr_result_t rv;
95     if (!srcud) return EXR_ERR_INVALID_ARGUMENT;
96     if (srcud->packed_data)
97         return exr_attr_opaquedata_create (
98             ctxt, ud, (size_t) srcud->size, srcud->packed_data);
99     rv = exr_attr_opaquedata_init (ctxt, ud, 0);
100     if (rv == EXR_ERR_SUCCESS)
101         rv = exr_attr_opaquedata_set_unpacked (
102             ctxt, ud, srcud->unpacked_data, srcud->unpacked_size);
103     return rv;
104 }
105 
106 /**************************************/
107 
108 exr_result_t
exr_attr_opaquedata_unpack(exr_context_t ctxt,exr_attr_opaquedata_t * u,int32_t * sz,void ** unpacked)109 exr_attr_opaquedata_unpack (
110     exr_context_t ctxt, exr_attr_opaquedata_t* u, int32_t* sz, void** unpacked)
111 {
112     exr_result_t rv;
113     int32_t tmpusz;
114     void *tmpuptr;
115 
116     INTERN_EXR_PROMOTE_CONTEXT_OR_ERROR (ctxt);
117 
118     if (sz) *sz = 0;
119     if (unpacked) *unpacked = NULL;
120 
121     if (!u)
122         return pctxt->report_error (
123             pctxt,
124             EXR_ERR_INVALID_ARGUMENT,
125             "Invalid reference to opaque data object to initialize");
126 
127     if (u->unpacked_data)
128     {
129         if (sz) *sz = u->unpacked_size;
130         if (unpacked) *unpacked = u->unpacked_data;
131         return EXR_ERR_SUCCESS;
132     }
133 
134     if (!u->unpack_func_ptr)
135         return pctxt->report_error (
136             pctxt,
137             EXR_ERR_INVALID_ARGUMENT,
138             "No unpack provider specified for opaque data");
139     rv = u->unpack_func_ptr (
140         ctxt,
141         u->packed_data,
142         u->size,
143         &(tmpusz),
144         &(tmpuptr));
145     if (rv == EXR_ERR_SUCCESS)
146     {
147         u->unpacked_size = tmpusz;
148         u->unpacked_data = tmpuptr;
149         if (sz) *sz = tmpusz;
150         if (unpacked) *unpacked = tmpuptr;
151     }
152 
153     return rv;
154 }
155 
156 /**************************************/
157 
158 exr_result_t
exr_attr_opaquedata_pack(exr_context_t ctxt,exr_attr_opaquedata_t * u,int32_t * sz,void ** packed)159 exr_attr_opaquedata_pack (
160     exr_context_t ctxt, exr_attr_opaquedata_t* u, int32_t* sz, void** packed)
161 {
162     exr_result_t rv;
163     int32_t      nsize  = 0;
164     void*        tmpptr = NULL;
165 
166     INTERN_EXR_PROMOTE_CONTEXT_OR_ERROR (ctxt);
167 
168     if (sz) *sz = 0;
169     if (packed) *packed = NULL;
170 
171     if (!u)
172         return pctxt->report_error (
173             pctxt,
174             EXR_ERR_INVALID_ARGUMENT,
175             "Invalid reference to opaque data object to initialize");
176 
177     if (u->packed_data)
178     {
179         if (sz) *sz = u->size;
180         if (packed) *packed = u->packed_data;
181         return EXR_ERR_SUCCESS;
182     }
183 
184     if (!u->pack_func_ptr)
185         return pctxt->report_error (
186             pctxt,
187             EXR_ERR_INVALID_ARGUMENT,
188             "No pack provider specified for opaque data");
189 
190     rv = u->pack_func_ptr (
191         ctxt, u->unpacked_data, u->unpacked_size, &nsize, NULL);
192     if (rv != EXR_ERR_SUCCESS)
193         return pctxt->print_error (
194             pctxt,
195             rv,
196             "Pack function failed finding pack buffer size, unpacked size %d",
197             u->unpacked_size);
198 
199     if (nsize > 0)
200     {
201         tmpptr = pctxt->alloc_fn ((size_t) nsize);
202         if (tmpptr == NULL)
203             return pctxt->standard_error (pctxt, EXR_ERR_OUT_OF_MEMORY);
204 
205         u->packed_alloc_size = nsize;
206 
207         rv = u->pack_func_ptr (
208             ctxt, u->unpacked_data, u->unpacked_size, &nsize, tmpptr);
209         if (rv != EXR_ERR_SUCCESS)
210         {
211             pctxt->free_fn (tmpptr);
212             nsize                = u->packed_alloc_size;
213             u->packed_alloc_size = 0;
214             return pctxt->print_error (
215                 pctxt,
216                 rv,
217                 "Pack function failed to pack data, unpacked size %d, packed buffer size %d",
218                 u->unpacked_size,
219                 nsize);
220         }
221         u->size        = nsize;
222         u->packed_data = tmpptr;
223         if (sz) *sz = nsize;
224         if (packed) *packed = tmpptr;
225 
226         if (u->destroy_unpacked_func_ptr)
227             u->destroy_unpacked_func_ptr (
228                 ctxt, u->unpacked_data, u->unpacked_size);
229         u->unpacked_data = NULL;
230         u->unpacked_size = 0;
231     }
232     return rv;
233 }
234 
235 /**************************************/
236 
237 exr_result_t
exr_attr_opaquedata_set_unpacked(exr_context_t ctxt,exr_attr_opaquedata_t * u,void * unpacked,int32_t sz)238 exr_attr_opaquedata_set_unpacked (
239     exr_context_t ctxt, exr_attr_opaquedata_t* u, void* unpacked, int32_t sz)
240 {
241     INTERN_EXR_PROMOTE_CONTEXT_OR_ERROR (ctxt);
242 
243     if (!u) return pctxt->standard_error (pctxt, EXR_ERR_INVALID_ARGUMENT);
244 
245     /* TODO: do we care if the incoming unpacked data is null? */
246     if (sz < 0)
247         return pctxt->print_error (
248             pctxt,
249             EXR_ERR_INVALID_ARGUMENT,
250             "Opaque data given invalid negative size (%d)",
251             sz);
252 
253     if (u->unpacked_data)
254     {
255         if (u->destroy_unpacked_func_ptr)
256             u->destroy_unpacked_func_ptr (
257                 ctxt, u->unpacked_data, u->unpacked_size);
258     }
259     u->unpacked_data = unpacked;
260     u->unpacked_size = sz;
261 
262     if (u->packed_data)
263     {
264         if (u->packed_alloc_size > 0) pctxt->free_fn (u->packed_data);
265         u->packed_data       = NULL;
266         u->size              = 0;
267         u->packed_alloc_size = 0;
268     }
269     return EXR_ERR_SUCCESS;
270 }
271 
272 /**************************************/
273 
274 exr_result_t
exr_attr_opaquedata_set_packed(exr_context_t ctxt,exr_attr_opaquedata_t * u,const void * packed,int32_t sz)275 exr_attr_opaquedata_set_packed (
276     exr_context_t          ctxt,
277     exr_attr_opaquedata_t* u,
278     const void*            packed,
279     int32_t                sz)
280 {
281     void* nmem;
282     INTERN_EXR_PROMOTE_CONTEXT_OR_ERROR (ctxt);
283 
284     if (!u) return pctxt->standard_error (pctxt, EXR_ERR_INVALID_ARGUMENT);
285 
286     /* TODO: do we care if the incoming unpacked data is null? */
287     if (sz < 0)
288         return pctxt->print_error (
289             pctxt,
290             EXR_ERR_INVALID_ARGUMENT,
291             "Opaque data given invalid negative size (%d)",
292             sz);
293 
294     nmem = pctxt->alloc_fn ((size_t)sz);
295     if (!nmem) return pctxt->standard_error (pctxt, EXR_ERR_OUT_OF_MEMORY);
296 
297     if (u->unpacked_data)
298     {
299         if (u->destroy_unpacked_func_ptr)
300             u->destroy_unpacked_func_ptr (
301                 ctxt, u->unpacked_data, u->unpacked_size);
302     }
303     u->unpacked_data = NULL;
304     u->unpacked_size = 0;
305 
306     if (u->packed_data)
307     {
308         if (u->packed_alloc_size > 0) pctxt->free_fn (u->packed_data);
309         u->packed_data       = NULL;
310         u->size              = 0;
311         u->packed_alloc_size = 0;
312     }
313 
314     u->packed_data       = nmem;
315     u->size              = sz;
316     u->packed_alloc_size = sz;
317     if (packed) memcpy ((void*) u->packed_data, packed, (size_t)sz);
318 
319     return EXR_ERR_SUCCESS;
320 }
321