1 /****************************************************************************\
2  *  pack.h - definitions for lowest level un/pack functions. all functions
3  *	utilize a Buf structure. Call init_buf, un/pack, and free_buf
4  *****************************************************************************
5  *  Copyright (C) 2002-2007 The Regents of the University of California.
6  *  Copyright (C) 2008 Lawrence Livermore National Security.
7  *  Produced at Lawrence Livermore National Laboratory (cf, DISCLAIMER).
8  *  Written by Kevin Tew <tew1@llnl.gov>, Morris Jette <jette1@llnl.gov>, et. al.
9  *  CODE-OCEC-09-009. All rights reserved.
10  *
11  *  This file is part of Slurm, a resource management program.
12  *  For details, see <https://slurm.schedmd.com/>.
13  *  Please also read the included file: DISCLAIMER.
14  *
15  *  Slurm is free software; you can redistribute it and/or modify it under
16  *  the terms of the GNU General Public License as published by the Free
17  *  Software Foundation; either version 2 of the License, or (at your option)
18  *  any later version.
19  *
20  *  In addition, as a special exception, the copyright holders give permission
21  *  to link the code of portions of this program with the OpenSSL library under
22  *  certain conditions as described in each individual source file, and
23  *  distribute linked combinations including the two. You must obey the GNU
24  *  General Public License in all respects for all of the code used other than
25  *  OpenSSL. If you modify file(s) with this exception, you may extend this
26  *  exception to your version of the file(s), but you are not obligated to do
27  *  so. If you do not wish to do so, delete this exception statement from your
28  *  version.  If you delete this exception statement from all source files in
29  *  the program, then also delete it here.
30  *
31  *  Slurm is distributed in the hope that it will be useful, but WITHOUT ANY
32  *  WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
33  *  FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
34  *  details.
35  *
36  *  You should have received a copy of the GNU General Public License along
37  *  with Slurm; if not, write to the Free Software Foundation, Inc.,
38  *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301  USA.
39 \****************************************************************************/
40 
41 #ifndef _PACK_INCLUDED
42 #define _PACK_INCLUDED
43 
44 #include <assert.h>
45 #include <inttypes.h>
46 #include <time.h>
47 #include <stdbool.h>
48 #include <string.h>
49 
50 #include "src/common/bitstring.h"
51 
52 #define BUF_MAGIC 0x42554545
53 #define BUF_SIZE (16 * 1024)
54 #define MAX_BUF_SIZE ((uint32_t) 0xffff0000)	/* avoid going over 32-bits */
55 #define REASONABLE_BUF_SIZE ((uint32_t) 0xbfff4000) /* three-quarters of max */
56 #define FLOAT_MULT 1000000
57 
58 /* If we unpack a buffer that contains bad data, we want to avoid a memory
59  * allocation error due to array or buffer sizes that are unreasonably large */
60 #define MAX_PACK_ARRAY_LEN	(128 * 1024)
61 #define MAX_PACK_MEM_LEN	(1024 * 1024 * 1024)
62 
63 typedef struct slurm_buf {
64 	uint32_t magic;
65 	char *head;
66 	uint32_t size;
67 	uint32_t processed;
68 	bool mmaped;
69 } buf_t;
70 
71 typedef struct slurm_buf * Buf;
72 
73 #define get_buf_data(__buf)		(__buf->head)
74 #define get_buf_offset(__buf)		(__buf->processed)
75 #define set_buf_offset(__buf,__val)	(__buf->processed = __val)
76 #define remaining_buf(__buf)		(__buf->size - __buf->processed)
77 #define size_buf(__buf)			(__buf->size)
78 
79 Buf	create_buf (char *data, uint32_t size);
80 Buf	create_mmap_buf(char *file);
81 void	free_buf(Buf my_buf);
82 Buf	init_buf(uint32_t size);
83 void    grow_buf (Buf my_buf, uint32_t size);
84 void	*xfer_buf_data(Buf my_buf);
85 
86 void	pack_time(time_t val, Buf buffer);
87 int	unpack_time(time_t *valp, Buf buffer);
88 
89 void 	packfloat(float val, Buf buffer);
90 int	unpackfloat(float *valp, Buf buffer);
91 
92 void 	packdouble(double val, Buf buffer);
93 int	unpackdouble(double *valp, Buf buffer);
94 
95 void 	packlongdouble(long double val, Buf buffer);
96 int	unpacklongdouble(long double *valp, Buf buffer);
97 
98 void 	pack64(uint64_t val, Buf buffer);
99 int	unpack64(uint64_t *valp, Buf buffer);
100 
101 void 	pack32(uint32_t val, Buf buffer);
102 int	unpack32(uint32_t *valp, Buf buffer);
103 
104 void	pack16(uint16_t val, Buf buffer);
105 int	unpack16(uint16_t *valp, Buf buffer);
106 
107 void	pack8(uint8_t val, Buf buffer);
108 int	unpack8(uint8_t *valp, Buf buffer);
109 
110 void	packbool(bool val, Buf buffer);
111 int	unpackbool(bool *valp, Buf buffer);
112 
113 void    pack16_array(uint16_t *valp, uint32_t size_val, Buf buffer);
114 int     unpack16_array(uint16_t **valp, uint32_t* size_val, Buf buffer);
115 
116 void	pack32_array(uint32_t *valp, uint32_t size_val, Buf buffer);
117 int	unpack32_array(uint32_t **valp, uint32_t* size_val, Buf buffer);
118 
119 void	pack64_array(uint64_t *valp, uint32_t size_val, Buf buffer);
120 int	unpack64_array(uint64_t **valp, uint32_t* size_val, Buf buffer);
121 
122 void	pack64_array_as_32(uint64_t * valp, uint32_t size_val, Buf buffer);
123 int	unpack64_array_from_32(uint64_t ** valp, uint32_t * size_val, Buf buffer);
124 
125 void	packdouble_array(double *valp, uint32_t size_val, Buf buffer);
126 int	unpackdouble_array(double **valp, uint32_t* size_val, Buf buffer);
127 
128 void	packlongdouble_array(long double *valp, uint32_t size_val, Buf buffer);
129 int	unpacklongdouble_array(long double **valp, uint32_t* size_val,
130 			       Buf buffer);
131 
132 void	packmem(char *valp, uint32_t size_val, Buf buffer);
133 int	unpackmem(char *valp, uint32_t *size_valp, Buf buffer);
134 int	unpackmem_ptr(char **valp, uint32_t *size_valp, Buf buffer);
135 int	unpackmem_xmalloc(char **valp, uint32_t *size_valp, Buf buffer);
136 int	unpackmem_malloc(char **valp, uint32_t *size_valp, Buf buffer);
137 
138 int	unpackstr_xmalloc_escaped(char **valp, uint32_t *size_valp, Buf buffer);
139 int	unpackstr_xmalloc_chooser(char **valp, uint32_t *size_valp, Buf buffer);
140 
141 void	packstr_array(char **valp, uint32_t size_val, Buf buffer);
142 int	unpackstr_array(char ***valp, uint32_t* size_val, Buf buffer);
143 
144 void	packmem_array(char *valp, uint32_t size_val, Buf buffer);
145 int	unpackmem_array(char *valp, uint32_t size_valp, Buf buffer);
146 
147 #define safe_unpack_time(valp,buf) do {			\
148 	assert(sizeof(*valp) == sizeof(time_t));	\
149 	assert(buf->magic == BUF_MAGIC);		\
150         if (unpack_time(valp,buf))			\
151 		goto unpack_error;			\
152 } while (0)
153 
154 #define safe_unpackfloat(valp,buf) do {		\
155 	assert(sizeof(*valp) == sizeof(float));        \
156 	assert(buf->magic == BUF_MAGIC);		\
157         if (unpackfloat(valp,buf))			\
158 		goto unpack_error;			\
159 } while (0)
160 
161 #define safe_unpackdouble(valp,buf) do {		\
162 	assert(sizeof(*valp) == sizeof(double));        \
163 	assert(buf->magic == BUF_MAGIC);		\
164         if (unpackdouble(valp,buf))			\
165 		goto unpack_error;			\
166 } while (0)
167 
168 #define safe_unpacklongdouble(valp,buf) do {		\
169 	assert(sizeof(*valp) == sizeof(long double));	\
170 	assert(buf->magic == BUF_MAGIC);		\
171         if (unpacklongdouble(valp,buf))			\
172 		goto unpack_error;			\
173 } while (0)
174 
175 #define safe_unpack64(valp,buf) do {			\
176 	assert(sizeof(*valp) == sizeof(uint64_t));      \
177 	assert(buf->magic == BUF_MAGIC);		\
178         if (unpack64(valp,buf))				\
179 		goto unpack_error;			\
180 } while (0)
181 
182 #define safe_unpack32(valp,buf) do {			\
183 	assert(sizeof(*valp) == sizeof(uint32_t));      \
184 	assert(buf->magic == BUF_MAGIC);		\
185         if (unpack32(valp,buf))				\
186 		goto unpack_error;			\
187 } while (0)
188 
189 #define safe_unpack16(valp,buf) do {			\
190 	assert(sizeof(*valp) == sizeof(uint16_t)); 	\
191 	assert(buf->magic == BUF_MAGIC);		\
192         if (unpack16(valp,buf))				\
193 		goto unpack_error;			\
194 } while (0)
195 
196 #define safe_unpack8(valp,buf) do {			\
197 	assert(sizeof(*valp) == sizeof(uint8_t)); 	\
198 	assert(buf->magic == BUF_MAGIC);		\
199         if (unpack8(valp,buf))				\
200 		goto unpack_error;			\
201 } while (0)
202 
203 #define safe_unpackbool(valp,buf) do {			\
204 	assert(sizeof(*valp) == sizeof(bool)); 	\
205 	assert(buf->magic == BUF_MAGIC);		\
206         if (unpackbool(valp,buf))				\
207 		goto unpack_error;			\
208 } while (0)
209 
210 #define safe_unpack16_array(valp,size_valp,buf) do {    \
211         assert(sizeof(*size_valp) == sizeof(uint32_t)); \
212         assert(buf->magic == BUF_MAGIC);                \
213         if (unpack16_array(valp,size_valp,buf))         \
214                 goto unpack_error;                      \
215 } while (0)
216 
217 #define safe_unpack32_array(valp,size_valp,buf) do {	\
218 	assert(sizeof(*size_valp) == sizeof(uint32_t)); \
219 	assert(buf->magic == BUF_MAGIC);		\
220 	if (unpack32_array(valp,size_valp,buf))		\
221 		goto unpack_error;			\
222 } while (0)
223 
224 #define safe_unpack64_array(valp,size_valp,buf) do {	\
225 	assert(sizeof(*size_valp) == sizeof(uint32_t)); \
226 	assert(buf->magic == BUF_MAGIC);		\
227 	if (unpack64_array(valp,size_valp,buf))		\
228 		goto unpack_error;			\
229 } while (0)
230 
231 #define safe_unpack64_array_from_32(valp,size_valp,buf) do {	\
232 	assert(sizeof(*size_valp) == sizeof(uint32_t)); \
233 	assert(buf->magic == BUF_MAGIC);		\
234 	if (unpack64_array_from_32(valp,size_valp,buf))	\
235 		goto unpack_error;			\
236 } while (0)
237 
238 #define safe_unpackdouble_array(valp,size_valp,buf) do {	\
239 	assert(sizeof(*size_valp) == sizeof(uint32_t)); \
240 	assert(buf->magic == BUF_MAGIC);		\
241 	if (unpackdouble_array(valp,size_valp,buf))	\
242 		goto unpack_error;			\
243 } while (0)
244 
245 #define safe_unpacklongdouble_array(valp,size_valp,buf) do {	\
246 	assert(sizeof(*size_valp) == sizeof(uint32_t)); \
247 	assert(buf->magic == BUF_MAGIC);		\
248 	if (unpacklongdouble_array(valp,size_valp,buf))	\
249 		goto unpack_error;			\
250 } while (0)
251 
252 #define safe_unpackmem(valp,size_valp,buf) do {		\
253 	assert(sizeof(*size_valp) == sizeof(uint32_t)); \
254 	assert(buf->magic == BUF_MAGIC);		\
255 	if (unpackmem(valp,size_valp,buf))		\
256 		goto unpack_error;			\
257 } while (0)
258 
259 #define safe_unpackmem_ptr(valp,size_valp,buf) do {	\
260 	assert(sizeof(*size_valp) == sizeof(uint32_t)); \
261 	assert(buf->magic == BUF_MAGIC);		\
262 	if (unpackmem_ptr(valp,size_valp,buf))		\
263 		goto unpack_error;			\
264 } while (0)
265 
266 #define safe_unpackmem_xmalloc(valp,size_valp,buf) do {	\
267 	assert(sizeof(*size_valp) == sizeof(uint32_t)); \
268 	assert(buf->magic == BUF_MAGIC);		\
269 	if (unpackmem_xmalloc(valp,size_valp,buf))	\
270 		goto unpack_error;			\
271 } while (0)
272 
273 #define safe_unpackmem_malloc(valp,size_valp,buf) do {	\
274 	assert(sizeof(*size_valp) == sizeof(uint32_t)); \
275 	assert(buf->magic == BUF_MAGIC);		\
276 	if (unpackmem_malloc(valp,size_valp,buf))	\
277 		goto unpack_error;			\
278 } while (0)
279 
280 #define packstr(str,buf) do {				\
281 	uint32_t _size = 0;				\
282 	if((char *)str != NULL)				\
283 		_size = (uint32_t)strlen(str)+1;	\
284         assert(_size == 0 || str != NULL);             	\
285 	assert(_size <= 0xffffffff);			\
286 	assert(buf->magic == BUF_MAGIC);		\
287 	packmem(str,(uint32_t)_size,buf);		\
288 } while (0)
289 
290 #define packnull(buf) do { \
291 	assert(buf != NULL); \
292 	assert(buf->magic == BUF_MAGIC); \
293 	packmem(NULL, 0, buf); \
294 } while (0)
295 
296 #define pack_bit_str_hex(bitmap,buf) do {		\
297 	assert(buf->magic == BUF_MAGIC);		\
298 	if (bitmap) {					\
299 		char *_tmp_str;				\
300 		uint32_t _size;				\
301 		_tmp_str = bit_fmt_hexmask(bitmap);	\
302 		_size = bit_size(bitmap);               \
303 		pack32(_size, buf);              	\
304 		_size = strlen(_tmp_str)+1;		\
305 		packmem(_tmp_str,_size,buf);	        \
306 		xfree(_tmp_str);			\
307 	} else						\
308 		pack32(NO_VAL, buf);                 	\
309 } while (0)
310 
311 #define unpack_bit_str_hex(bitmap,buf) do {				\
312 	char *tmp_str = NULL;						\
313 	uint32_t _size, _tmp_uint32;					\
314 	assert(*bitmap == NULL);					\
315 	assert(buf->magic == BUF_MAGIC);				\
316 	safe_unpack32(&_size, buf);					\
317 	if (_size != NO_VAL) {						\
318 		safe_unpackstr_xmalloc(&tmp_str, &_tmp_uint32, buf);	\
319 		if (_size) {						\
320 			*bitmap = bit_alloc(_size);			\
321 			if (bit_unfmt_hexmask(*bitmap, tmp_str)) {	\
322 				FREE_NULL_BITMAP(*bitmap);		\
323 				xfree(tmp_str);				\
324 				goto unpack_error;			\
325 			}						\
326 		} else							\
327 			*bitmap = NULL;					\
328 		xfree(tmp_str);						\
329 	} else								\
330 		*bitmap = NULL;						\
331 } while (0)
332 
333 /* note: this would be faster if collapsed into a single function
334  * rather than a combination of unpack_bit_str_hex and bitstr2inx */
335 #define unpack_bit_str_hex_as_inx(inx, buf) do {	\
336 	bitstr_t *b = NULL;				\
337 	unpack_bit_str_hex(&b, buf);			\
338 	*inx = bitstr2inx(b);				\
339 	FREE_NULL_BITMAP(b);				\
340 } while (0)
341 
342 #define unpackstr_malloc	                        \
343         unpackmem_malloc
344 
345 #define unpackstr_xmalloc	                        \
346         unpackmem_xmalloc
347 
348 #define safe_unpackstr_malloc	                        \
349         safe_unpackmem_malloc
350 
351 #define safe_unpackstr_xmalloc(valp, size_valp, buf) do {	\
352 	assert(sizeof(*size_valp) == sizeof(uint32_t));        	\
353 	assert(buf->magic == BUF_MAGIC);		        \
354 	if (unpackstr_xmalloc_chooser(valp, size_valp, buf))    \
355 		goto unpack_error;		       		\
356 } while (0)
357 
358 #define safe_unpackstr_array(valp,size_valp,buf) do {	\
359 	assert(sizeof(*size_valp) == sizeof(uint32_t)); \
360 	assert(buf->magic == BUF_MAGIC);		\
361 	if (unpackstr_array(valp,size_valp,buf))	\
362 		goto unpack_error;			\
363 } while (0)
364 
365 #define safe_unpackmem_array(valp,size,buf) do {	\
366 	assert(valp != NULL);				\
367 	assert(sizeof(size) == sizeof(uint32_t)); 	\
368 	assert(buf->magic == BUF_MAGIC);		\
369 	if (unpackmem_array(valp,size,buf))		\
370 		goto unpack_error;			\
371 } while (0)
372 
373 #define safe_xcalloc(p, cnt, sz) do {			\
374 	size_t _cnt = cnt;				\
375 	size_t _sz = sz;				\
376 	if (!_cnt || !_sz)				\
377 		p = NULL;				\
378 	else if (!(p = try_xcalloc(_cnt, _sz)))		\
379 		goto unpack_error;			\
380 } while (0)
381 
382 #define safe_xmalloc(p, sz) do {			\
383 	size_t _sz = sz;				\
384 	if (!_sz)					\
385 		p = NULL;				\
386 	else if (!(p = try_xmalloc(_sz)))		\
387 		goto unpack_error;			\
388 } while (0)
389 
390 #define FREE_NULL_BUFFER(_X)		\
391 	do {				\
392 		if (_X) free_buf (_X);	\
393 		_X	= NULL; 	\
394 	} while (0)
395 
396 #endif /* _PACK_INCLUDED */
397