Bitdefender Hypervisor Memory Introspection
conv.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2020 Bitdefender
3  * SPDX-License-Identifier: Apache-2.0
4  */
5 #include "introtypes.h"
6 
7 //
8 // ANSI character macros
9 //
10 #define crt_tolower(c) ((((c) >= 'A') && ((c) <= 'Z')) ? ((c) - 'A' + 'a') : (c))
11 #define crt_toupper(c) ((((c) >= 'a') && ((c) <= 'z')) ? ((c) - 'a' + 'A') : (c))
12 
13 int
14 tolower(int c)
15 {
16  return crt_tolower(c);
17 }
18 
19 int
20 toupper(int c)
21 {
22  return crt_toupper(c);
23 }
24 
25 #define isalpha(c) (((((c) >= 'A') && ((c) <= 'Z')) || (((c) >= 'a') && ((c) <= 'z'))) ? 1 : 0)
26 
27 #define isdigit(c) ((((c) >= '0') && ((c) <= '9')) ? 1 : 0)
28 
29 #define isxdigit(c) (((((c) >= 'A') && ((c) <= 'F')) || (((c) >= 'a') && \
30  ((c) <= 'f')) || (((c) >= '0') && ((c) <= '9'))) ? 1 : 0)
31 
32 #define isprint(c) (((c) >= ' ' && (c) <= '~') ? 1 : 0)
33 #define isspace(c) (((c) == ' ') || ((c) == '\t') || ((c) == '\n') || ((c) == '\v') || ((c) == '\f') || ((c) == '\r'))
34 
35 //
36 // helper routines
37 //
38 
39 /***
40 *crt_strtol, crt_strtoul(nptr,endptr,ibase) - Convert ascii string to INT32 un/INT32
41 * INT32.
42 *
43 *Purpose:
44 * Convert an ascii string to a INT32 32-bit value. The base
45 * used for the caculations is supplied by the caller. The base
46 * must be in the range 0, 2-36. If a base of 0 is supplied, the
47 * ascii string must be examined to determine the base of the
48 * number:
49 * (a) First INT8 = '0', second INT8 = 'x' or 'X',
50 * use base 16.
51 * (b) First INT8 = '0', use base 8
52 * (c) First INT8 in range '1' - '9', use base 10.
53 *
54 * If the 'endptr' value is non-NULL, then crt_strtol/crt_strtoul places
55 * a pointer to the terminating character in this value.
56 * See ANSI standard for details
57 *
58 *Entry:
59 * nptr == NEAR/FAR pointer to the start of string.
60 * endptr == NEAR/FAR pointer to the end of the string.
61 * ibase == integer base to use for the calculations.
62 *
63 * string format: [whitespace] [sign] [0] [x] [digits/letters]
64 *
65 *Exit:
66 * Good return:
67 * result
68 *
69 * Overflow return:
70 * crt_strtol -- INT32_MAX or INT32_MIN
71 * crt_strtoul -- UINT32_MAX
72 * crt_strtol/crt_strtoul -- errno == ERANGE
73 *
74 * No digits or bad base return:
75 * 0
76 * endptr = nptr*
77 *
78 *Exceptions:
79 * Input parameters are validated. Refer to the validation section of the function.
80 *
81 *******************************************************************************/
82 
83 /* flag values */
84 #define FL_UNSIGNED 1 /* crt_strtoul called */
85 #define FL_NEG 2 /* negative sign found */
86 #define FL_OVERFLOW 4 /* overflow occurred */
87 #define FL_READDIGIT 8 /* we've read at least one correct digit */
88 
89 static UINT32 __cdecl
91  const INT8 *nptr,
92  const INT8 **endptr,
93  INT32 ibase,
94  INT32 flags
95  )
96 {
97  const INT8 *p;
98  INT8 c;
99  UINT32 number;
100  UINT32 digval;
101  UINT32 maxval;
102 
103  /* validation section */
104  if (endptr != NULL)
105  {
106  /* store beginning of string in endptr */
107  *endptr = (INT8 *)nptr;
108  }
109 
113 
114  p = nptr; /* p is our scanning pointer */
115  number = 0; /* start with zero */
116 
117  c = *p++; /* read INT8 */
119  while (' ' == (INT32)(UINT8)c)
120  c = *p++; /* skip whitespace */
121 
122  if (c == '-')
123  {
124  flags |= FL_NEG; /* remember minus sign */
125  c = *p++;
126  }
127  else if (c == '+')
128  c = *p++; /* skip sign */
129 
130  if (ibase < 0 || ibase == 1 || ibase > 36)
131  {
132  /* bad base! */
133  if (endptr)
134  /* store beginning of string in endptr */
135  *endptr = nptr;
136  return 0L; /* return 0 */
137  }
138  else if (ibase == 0)
139  {
140  /* determine base free-lance, based on first two chars of
141  string */
142  if (c != '0')
143  ibase = 10;
144  else if (*p == 'x' || *p == 'X')
145  ibase = 16;
146  else
147  ibase = 8;
148  }
149 
150  if (ibase == 0)
151  {
152  /* determine base free-lance, based on first two chars of
153  string */
154  if (c != '0')
155  ibase = 10;
156  else if (*p == 'x' || *p == 'X')
157  ibase = 16;
158  else
159  ibase = 8;
160  }
161 
162  if (ibase == 16)
163  {
164  /* we might have 0x in front of number; remove if there */
165  if (c == '0' && (*p == 'x' || *p == 'X'))
166  {
167  ++p;
168  c = *p++; /* advance past prefix */
169  }
170  }
171 
172  /* if our number exceeds this, we will overflow on multiply */
173  maxval = INT32_MAX / ibase;
174 
175 
176  for (;;)
177  {
178  /* exit in middle of loop */
179  /* convert c to value */
181  if (isdigit((INT32)(UINT8)c))
182  digval = c - '0';
184  else if (isalpha((INT32)(UINT8)c))
186  digval = toupper(c) - 'A' + 10;
187  else
188  break;
189  if (digval >= (UINT32)ibase)
190  break; /* exit loop if bad digit found */
191 
192  /* record the fact we have read one digit */
193  flags |= FL_READDIGIT;
194 
195  /* we now need to compute number = number * base + digval,
196  but we need to know if overflow occurred. This requires
197  a tricky pre-check. */
198 
199  if (number < maxval || (number == maxval && (UINT32)digval <= UINT32_MAX % ibase))
200  {
201  /* we won't overflow, go ahead and multiply */
202  number = number * ibase + digval;
203  }
204  else
205  {
206  /* we would have overflowed -- set the overflow flag */
207  flags |= FL_OVERFLOW;
208  if (endptr == NULL)
209  {
210  /* no need to keep on parsing if we
211  don't have to return the endptr. */
212  break;
213  }
214  }
215 
216  c = *p++; /* read next digit */
217  }
218 
219  --p; /* point to place that stopped scan */
220 
221  if (!(flags & FL_READDIGIT))
222  {
223  /* no number there; return 0 and point to beginning of
224  string */
225  if (endptr)
226  /* store beginning of string in endptr later on */
227  p = nptr;
228  number = 0L; /* return 0 */
229  }
230  else if ((flags & FL_OVERFLOW) || (!(flags & FL_UNSIGNED) && (((flags & FL_NEG) && (number > -INT32_MIN)) ||
231  (!(flags & FL_NEG) && (number > INT32_MAX)))))
232  {
233  /* overflow or INT32 overflow occurred */
235  if (flags & FL_UNSIGNED)
236  number = INT32_MAX;
237  else if (flags & FL_NEG)
238  number = (UINT32)(-INT32_MIN);
239  else
240  number = INT32_MAX;
241  }
242 
243  if (endptr != NULL)
244  /* store pointer to INT8 that stopped the scan */
245  *endptr = p;
246 
247  if (flags & FL_NEG)
248  /* negate result if there was a neg sign */
249  number = (UINT32)(-(INT32)number);
250 
251  return number; /* done. */
252 }
253 
254 static UINT64 __cdecl
256  const INT8 *nptr,
257  const INT8 **endptr,
258  INT32 ibase,
259  INT32 flags
260  )
261 {
262  const INT8 *p;
263  INT8 c;
264  UINT64 number;
265  UINT32 digval;
266  UINT64 maxval;
267 
268  /* validation section */
269  if (endptr != NULL)
270  {
271  /* store beginning of string in endptr */
272  *endptr = (INT8 *)nptr;
273  }
274 
278 
279  p = nptr; /* p is our scanning pointer */
280  number = 0; /* start with zero */
281 
282  c = *p++; /* read INT8 */
284  while (' ' == (INT32)(UINT8)c)
285  c = *p++; /* skip whitespace */
286 
287  if (c == '-')
288  {
289  flags |= FL_NEG; /* remember minus sign */
290  c = *p++;
291  }
292  else if (c == '+')
293  c = *p++; /* skip sign */
294 
295  if (ibase < 0 || ibase == 1 || ibase > 36)
296  {
297  /* bad base! */
298  if (endptr)
299  /* store beginning of string in endptr */
300  *endptr = nptr;
301  return 0L; /* return 0 */
302  }
303  else if (ibase == 0)
304  {
305  /* determine base free-lance, based on first two chars of
306  string */
307  if (c != '0')
308  ibase = 10;
309  else if (*p == 'x' || *p == 'X')
310  ibase = 16;
311  else
312  ibase = 8;
313  }
314 
315  if (ibase == 0)
316  {
317  /* determine base free-lance, based on first two chars of
318  string */
319  if (c != '0')
320  ibase = 10;
321  else if (*p == 'x' || *p == 'X')
322  ibase = 16;
323  else
324  ibase = 8;
325  }
326 
327  if (ibase == 16)
328  {
329  /* we might have 0x in front of number; remove if there */
330  if (c == '0' && (*p == 'x' || *p == 'X'))
331  {
332  ++p;
333  c = *p++; /* advance past prefix */
334  }
335  }
336 
337  /* if our number exceeds this, we will overflow on multiply */
338  maxval = UINT64_MAX / ibase;
339 
340 
341  for (;;)
342  {
343  /* exit in middle of loop */
344  /* convert c to value */
346  if (isdigit((INT32)(UINT8)c))
347  digval = c - '0';
349  else if (isalpha((INT32)(UINT8)c))
351  digval = toupper(c) - 'A' + 10;
352  else
353  break;
354  if (digval >= (UINT32)ibase)
355  break; /* exit loop if bad digit found */
356 
357  /* record the fact we have read one digit */
358  flags |= FL_READDIGIT;
359 
360  /* we now need to compute number = number * base + digval,
361  but we need to know if overflow occurred. This requires
362  a tricky pre-check. */
363 
364  if (number < maxval || (number == maxval && (UINT64)digval <= UINT64_MAX % ibase))
365  {
366  /* we won't overflow, go ahead and multiply */
367  number = number * ibase + digval;
368  }
369  else
370  {
371  /* we would have overflowed -- set the overflow flag */
372  flags |= FL_OVERFLOW;
373  if (endptr == NULL)
374  {
375  /* no need to keep on parsing if we
376  don't have to return the endptr. */
377  break;
378  }
379  }
380 
381  c = *p++; /* read next digit */
382  }
383 
384  --p; /* point to place that stopped scan */
385 
386  if (!(flags & FL_READDIGIT))
387  {
388  /* no number there; return 0 and point to beginning of
389  string */
390  if (endptr)
391  /* store beginning of string in endptr later on */
392  p = nptr;
393  number = 0L; /* return 0 */
394  }
395  else if ((flags & FL_OVERFLOW) || (!(flags & FL_UNSIGNED) && (((flags & FL_NEG) && (number > -INT64_MIN)) ||
396  (!(flags & FL_NEG) && (number > INT64_MAX)))))
397  {
398  /* overflow or INT32 overflow occurred */
400  if (flags & FL_UNSIGNED)
401  number = UINT64_MAX;
402  else if (flags & FL_NEG)
403  number = (UINT64)(-INT64_MIN);
404  else
405  number = INT64_MAX;
406  }
407 
408  if (endptr != NULL)
409  /* store pointer to INT8 that stopped the scan */
410  *endptr = p;
411 
412  if (flags & FL_NEG)
413  /* negate result if there was a neg sign */
414  number = (UINT64)(-(INT64)number);
415 
416  return number; /* done. */
417 }
418 
419 
420 //
421 // crt_strtol
422 //
423 INT32 __cdecl
425  _In_z_ const INT8 *nptr,
426  _Out_opt_ INT8 **endptr,
427  _In_ INT32 ibase
428  )
429 {
430  return (INT32)crt_strtoxl(nptr, (const INT8 **)endptr, ibase, 0);
431 }
432 
433 
434 //
435 // crt_strtoul
436 //
437 UINT32 __cdecl
439  _In_z_ const INT8 *nptr,
440  _Out_opt_ INT8 **endptr,
441  _In_ INT32 ibase
442  )
443 {
444  return crt_strtoxl(nptr, (const INT8 **)endptr, ibase, FL_UNSIGNED);
445 }
446 
447 
448 //
449 // crt_strtoll
450 //
451 INT64 __cdecl
453  _In_z_ const INT8 *nptr,
454  _Out_opt_ INT8 **endptr,
455  _In_ INT32 ibase
456  )
457 {
458  return (INT64)crt_strtoxll(nptr, (const INT8 **)endptr, ibase, 0);
459 }
460 
461 
462 //
463 // crt_strtoull
464 //
465 UINT64 __cdecl
467  _In_z_ const INT8 *nptr,
468  _Out_opt_ INT8 **endptr,
469  _In_ INT32 ibase
470  )
471 {
472  return crt_strtoxll(nptr, (const INT8 **)endptr, ibase, FL_UNSIGNED);
473 }
#define crt_toupper(c)
Definition: conv.c:11
uint8_t UINT8
Definition: intro_types.h:37
long long INT64
Definition: intro_types.h:45
#define isdigit(c)
Definition: conv.c:27
int toupper(int c)
Definition: conv.c:20
#define _In_
Definition: intro_sal.h:21
INT32 __cdecl strtol(const INT8 *nptr, INT8 **endptr, INT32 ibase)
Definition: conv.c:424
static UINT32 __cdecl crt_strtoxl(const INT8 *nptr, const INT8 **endptr, INT32 ibase, INT32 flags)
Definition: conv.c:90
#define FL_UNSIGNED
Definition: conv.c:84
uint32_t UINT32
Definition: intro_types.h:39
int32_t INT32
Definition: intro_types.h:44
#define isalpha(c)
Definition: conv.c:25
#define _Out_opt_
Definition: intro_sal.h:30
INT64 __cdecl strtoll(const INT8 *nptr, INT8 **endptr, INT32 ibase)
Definition: conv.c:452
#define FL_NEG
Definition: conv.c:85
unsigned long long UINT64
Definition: intro_types.h:40
UINT64 __cdecl strtoull(const INT8 *nptr, INT8 **endptr, INT32 ibase)
Definition: conv.c:466
UINT32 __cdecl strtoul(const INT8 *nptr, INT8 **endptr, INT32 ibase)
Definition: conv.c:438
#define _In_z_
Definition: intro_sal.h:17
#define crt_tolower(c)
Definition: conv.c:10
int8_t INT8
Definition: intro_types.h:42
int tolower(int c)
Definition: conv.c:14
#define FL_OVERFLOW
Definition: conv.c:86
static UINT64 __cdecl crt_strtoxll(const INT8 *nptr, const INT8 **endptr, INT32 ibase, INT32 flags)
Definition: conv.c:255
#define FL_READDIGIT
Definition: conv.c:87