Bug Summary

File:src/usr.bin/file/magic-load.c
Warning:line 1018, column 24
Access to field 'strength_operator' results in a dereference of a null pointer (loaded from variable 'ml')

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple amd64-unknown-openbsd7.0 -analyze -disable-free -disable-llvm-verifier -discard-value-names -main-file-name magic-load.c -analyzer-store=region -analyzer-opt-analyze-nested-blocks -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 1 -pic-is-pie -mframe-pointer=all -relaxed-aliasing -fno-rounding-math -mconstructor-aliases -munwind-tables -target-cpu x86-64 -target-feature +retpoline-indirect-calls -target-feature +retpoline-indirect-branches -tune-cpu generic -debugger-tuning=gdb -fcoverage-compilation-dir=/usr/src/usr.bin/file/obj -resource-dir /usr/local/lib/clang/13.0.0 -internal-isystem /usr/local/lib/clang/13.0.0/include -internal-externc-isystem /usr/include -O2 -fdebug-compilation-dir=/usr/src/usr.bin/file/obj -ferror-limit 19 -fwrapv -D_RET_PROTECTOR -ret-protector -fgnuc-version=4.2.1 -vectorize-loops -vectorize-slp -fno-builtin-malloc -fno-builtin-calloc -fno-builtin-realloc -fno-builtin-valloc -fno-builtin-free -fno-builtin-strdup -fno-builtin-strndup -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /home/ben/Projects/vmm/scan-build/2022-01-12-194120-40624-1 -x c /usr/src/usr.bin/file/magic-load.c
1/* $OpenBSD: magic-load.c,v 1.26 2017/07/02 10:58:15 brynet Exp $ */
2
3/*
4 * Copyright (c) 2015 Nicholas Marriott <nicm@openbsd.org>
5 *
6 * Permission to use, copy, modify, and distribute this software for any
7 * purpose with or without fee is hereby granted, provided that the above
8 * copyright notice and this permission notice appear in all copies.
9 *
10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14 * WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
15 * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
16 * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17 */
18
19#include <sys/types.h>
20
21#include <ctype.h>
22#include <err.h>
23#include <errno(*__errno()).h>
24#include <limits.h>
25#include <regex.h>
26#include <stdarg.h>
27#include <stdio.h>
28#include <stdlib.h>
29#include <string.h>
30
31#include "magic.h"
32#include "xmalloc.h"
33
34static int
35magic_odigit(u_char c)
36{
37 if (c >= '0' && c <= '7')
38 return (c - '0');
39 return (-1);
40}
41
42static int
43magic_xdigit(u_char c)
44{
45 if (c >= '0' && c <= '9')
46 return (c - '0');
47 if (c >= 'a' && c <= 'f')
48 return (10 + c - 'a');
49 if (c >= 'A' && c <= 'F')
50 return (10 + c - 'A');
51 return (-1);
52}
53
54static void
55magic_mark_text(struct magic_line *ml, int text)
56{
57 do {
58 ml->text = text;
59 ml = ml->parent;
60 } while (ml != NULL((void *)0));
61}
62
63static int
64magic_make_pattern(struct magic_line *ml, const char *name, regex_t *re,
65 const char *p)
66{
67 int error;
68 char errbuf[256];
69
70 error = regcomp(re, p, REG_EXTENDED0001|REG_NOSUB0004);
71 if (error != 0) {
72 regerror(error, re, errbuf, sizeof errbuf);
73 magic_warn(ml, "bad %s pattern: %s", name, errbuf);
74 return (-1);
75 }
76 return (0);
77}
78
79static int
80magic_set_result(struct magic_line *ml, const char *s)
81{
82 const char *fmt, *endfmt, *cp;
83 regex_t *re = NULL((void *)0);
84 regmatch_t pmatch;
85 size_t fmtlen;
86
87 while (isspace((u_char)*s))
88 s++;
89 if (*s == '\0') {
90 ml->result = NULL((void *)0);
91 return (0);
92 }
93 ml->result = xstrdup(s);
94
95 fmt = NULL((void *)0);
96 for (cp = s; *cp != '\0'; cp++) {
97 if (cp[0] == '%' && cp[1] != '%') {
98 if (fmt != NULL((void *)0)) {
99 magic_warn(ml, "multiple formats");
100 return (-1);
101 }
102 fmt = cp;
103 }
104 }
105 if (fmt == NULL((void *)0))
106 return (0);
107 fmt++;
108
109 for (endfmt = fmt; *endfmt != '\0'; endfmt++) {
110 if (strchr("diouxXeEfFgGsc", *endfmt) != NULL((void *)0))
111 break;
112 }
113 if (*endfmt == '\0') {
114 magic_warn(ml, "unterminated format");
115 return (-1);
116 }
117 fmtlen = endfmt + 1 - fmt;
118 if (fmtlen > 32) {
119 magic_warn(ml, "format too long");
120 return (-1);
121 }
122
123 if (*endfmt == 's') {
124 switch (ml->type) {
125 case MAGIC_TYPE_DATE:
126 case MAGIC_TYPE_LDATE:
127 case MAGIC_TYPE_UDATE:
128 case MAGIC_TYPE_ULDATE:
129 case MAGIC_TYPE_BEDATE:
130 case MAGIC_TYPE_BELDATE:
131 case MAGIC_TYPE_UBEDATE:
132 case MAGIC_TYPE_UBELDATE:
133 case MAGIC_TYPE_QDATE:
134 case MAGIC_TYPE_QLDATE:
135 case MAGIC_TYPE_UQDATE:
136 case MAGIC_TYPE_UQLDATE:
137 case MAGIC_TYPE_BEQDATE:
138 case MAGIC_TYPE_BEQLDATE:
139 case MAGIC_TYPE_UBEQDATE:
140 case MAGIC_TYPE_UBEQLDATE:
141 case MAGIC_TYPE_LEQDATE:
142 case MAGIC_TYPE_LEQLDATE:
143 case MAGIC_TYPE_ULEQDATE:
144 case MAGIC_TYPE_ULEQLDATE:
145 case MAGIC_TYPE_LEDATE:
146 case MAGIC_TYPE_LELDATE:
147 case MAGIC_TYPE_ULEDATE:
148 case MAGIC_TYPE_ULELDATE:
149 case MAGIC_TYPE_MEDATE:
150 case MAGIC_TYPE_MELDATE:
151 case MAGIC_TYPE_STRING:
152 case MAGIC_TYPE_PSTRING:
153 case MAGIC_TYPE_BESTRING16:
154 case MAGIC_TYPE_LESTRING16:
155 case MAGIC_TYPE_REGEX:
156 case MAGIC_TYPE_SEARCH:
157 break;
158 default:
159 ml->stringify = 1;
160 break;
161 }
162 }
163
164 if (!ml->root->compiled) {
165 /*
166 * XXX %ld (and %lu and so on) is invalid on 64-bit platforms
167 * with byte, short, long. We get lucky because our first and
168 * only argument ends up in a register. Accept it for now.
169 */
170 if (magic_make_pattern(ml, "short", &ml->root->format_short,
171 "^-?[0-9]*(\\.[0-9]*)?(c|(l|h|hh)?[iduxX])$") != 0)
172 return (-1);
173 if (magic_make_pattern(ml, "long", &ml->root->format_long,
174 "^-?[0-9]*(\\.[0-9]*)?(c|(l|h|hh)?[iduxX])$") != 0)
175 return (-1);
176 if (magic_make_pattern(ml, "quad", &ml->root->format_quad,
177 "^-?[0-9]*(\\.[0-9]*)?ll[iduxX]$") != 0)
178 return (-1);
179 if (magic_make_pattern(ml, "float", &ml->root->format_float,
180 "^-?[0-9]*(\\.[0-9]*)?[eEfFgG]$") != 0)
181 return (-1);
182 if (magic_make_pattern(ml, "string", &ml->root->format_string,
183 "^-?[0-9]*(\\.[0-9]*)?s$") != 0)
184 return (-1);
185 ml->root->compiled = 1;
186 }
187
188 if (ml->stringify)
189 re = &ml->root->format_string;
190 else {
191 switch (ml->type) {
192 case MAGIC_TYPE_NONE:
193 case MAGIC_TYPE_BESTRING16:
194 case MAGIC_TYPE_LESTRING16:
195 case MAGIC_TYPE_NAME:
196 case MAGIC_TYPE_USE:
197 return (0); /* don't use result */
198 case MAGIC_TYPE_BYTE:
199 case MAGIC_TYPE_UBYTE:
200 case MAGIC_TYPE_SHORT:
201 case MAGIC_TYPE_USHORT:
202 case MAGIC_TYPE_BESHORT:
203 case MAGIC_TYPE_UBESHORT:
204 case MAGIC_TYPE_LESHORT:
205 case MAGIC_TYPE_ULESHORT:
206 re = &ml->root->format_short;
207 break;
208 case MAGIC_TYPE_LONG:
209 case MAGIC_TYPE_ULONG:
210 case MAGIC_TYPE_BELONG:
211 case MAGIC_TYPE_UBELONG:
212 case MAGIC_TYPE_LELONG:
213 case MAGIC_TYPE_ULELONG:
214 case MAGIC_TYPE_MELONG:
215 re = &ml->root->format_long;
216 break;
217 case MAGIC_TYPE_QUAD:
218 case MAGIC_TYPE_UQUAD:
219 case MAGIC_TYPE_BEQUAD:
220 case MAGIC_TYPE_UBEQUAD:
221 case MAGIC_TYPE_LEQUAD:
222 case MAGIC_TYPE_ULEQUAD:
223 re = &ml->root->format_quad;
224 break;
225 case MAGIC_TYPE_FLOAT:
226 case MAGIC_TYPE_BEFLOAT:
227 case MAGIC_TYPE_LEFLOAT:
228 case MAGIC_TYPE_DOUBLE:
229 case MAGIC_TYPE_BEDOUBLE:
230 case MAGIC_TYPE_LEDOUBLE:
231 re = &ml->root->format_float;
232 break;
233 case MAGIC_TYPE_DATE:
234 case MAGIC_TYPE_LDATE:
235 case MAGIC_TYPE_UDATE:
236 case MAGIC_TYPE_ULDATE:
237 case MAGIC_TYPE_BEDATE:
238 case MAGIC_TYPE_BELDATE:
239 case MAGIC_TYPE_UBEDATE:
240 case MAGIC_TYPE_UBELDATE:
241 case MAGIC_TYPE_QDATE:
242 case MAGIC_TYPE_QLDATE:
243 case MAGIC_TYPE_UQDATE:
244 case MAGIC_TYPE_UQLDATE:
245 case MAGIC_TYPE_BEQDATE:
246 case MAGIC_TYPE_BEQLDATE:
247 case MAGIC_TYPE_UBEQDATE:
248 case MAGIC_TYPE_UBEQLDATE:
249 case MAGIC_TYPE_LEQDATE:
250 case MAGIC_TYPE_LEQLDATE:
251 case MAGIC_TYPE_ULEQDATE:
252 case MAGIC_TYPE_ULEQLDATE:
253 case MAGIC_TYPE_LEDATE:
254 case MAGIC_TYPE_LELDATE:
255 case MAGIC_TYPE_ULEDATE:
256 case MAGIC_TYPE_ULELDATE:
257 case MAGIC_TYPE_MEDATE:
258 case MAGIC_TYPE_MELDATE:
259 case MAGIC_TYPE_STRING:
260 case MAGIC_TYPE_PSTRING:
261 case MAGIC_TYPE_REGEX:
262 case MAGIC_TYPE_SEARCH:
263 case MAGIC_TYPE_DEFAULT:
264 case MAGIC_TYPE_CLEAR:
265 re = &ml->root->format_string;
266 break;
267 }
268 }
269
270 pmatch.rm_so = 0;
271 pmatch.rm_eo = fmtlen;
272 if (regexec(re, fmt, 1, &pmatch, REG_STARTEND00004) != 0) {
273 magic_warn(ml, "bad format for %s: %%%.*s", ml->type_string,
274 (int)fmtlen, fmt);
275 return (-1);
276 }
277
278 return (0);
279}
280
281static u_int
282magic_get_strength(struct magic_line *ml)
283{
284 int n;
285 size_t size;
286
287 if (ml->type == MAGIC_TYPE_NONE)
288 return (0);
289
290 if (ml->test_not || ml->test_operator == 'x') {
291 n = 1;
292 goto skip;
293 }
294
295 n = 2 * MAGIC_STRENGTH_MULTIPLIER10;
296 switch (ml->type) {
297 case MAGIC_TYPE_NONE:
298 case MAGIC_TYPE_DEFAULT:
299 return (0);
300 case MAGIC_TYPE_CLEAR:
301 case MAGIC_TYPE_NAME:
302 case MAGIC_TYPE_USE:
303 break;
304 case MAGIC_TYPE_BYTE:
305 case MAGIC_TYPE_UBYTE:
306 n += 1 * MAGIC_STRENGTH_MULTIPLIER10;
307 break;
308 case MAGIC_TYPE_SHORT:
309 case MAGIC_TYPE_USHORT:
310 case MAGIC_TYPE_BESHORT:
311 case MAGIC_TYPE_UBESHORT:
312 case MAGIC_TYPE_LESHORT:
313 case MAGIC_TYPE_ULESHORT:
314 n += 2 * MAGIC_STRENGTH_MULTIPLIER10;
315 break;
316 case MAGIC_TYPE_LONG:
317 case MAGIC_TYPE_ULONG:
318 case MAGIC_TYPE_FLOAT:
319 case MAGIC_TYPE_DATE:
320 case MAGIC_TYPE_LDATE:
321 case MAGIC_TYPE_UDATE:
322 case MAGIC_TYPE_ULDATE:
323 case MAGIC_TYPE_BELONG:
324 case MAGIC_TYPE_UBELONG:
325 case MAGIC_TYPE_BEFLOAT:
326 case MAGIC_TYPE_BEDATE:
327 case MAGIC_TYPE_BELDATE:
328 case MAGIC_TYPE_UBEDATE:
329 case MAGIC_TYPE_UBELDATE:
330 n += 4 * MAGIC_STRENGTH_MULTIPLIER10;
331 break;
332 case MAGIC_TYPE_QUAD:
333 case MAGIC_TYPE_UQUAD:
334 case MAGIC_TYPE_DOUBLE:
335 case MAGIC_TYPE_QDATE:
336 case MAGIC_TYPE_QLDATE:
337 case MAGIC_TYPE_UQDATE:
338 case MAGIC_TYPE_UQLDATE:
339 case MAGIC_TYPE_BEQUAD:
340 case MAGIC_TYPE_UBEQUAD:
341 case MAGIC_TYPE_BEDOUBLE:
342 case MAGIC_TYPE_BEQDATE:
343 case MAGIC_TYPE_BEQLDATE:
344 case MAGIC_TYPE_UBEQDATE:
345 case MAGIC_TYPE_UBEQLDATE:
346 case MAGIC_TYPE_LEQUAD:
347 case MAGIC_TYPE_ULEQUAD:
348 case MAGIC_TYPE_LEDOUBLE:
349 case MAGIC_TYPE_LEQDATE:
350 case MAGIC_TYPE_LEQLDATE:
351 case MAGIC_TYPE_ULEQDATE:
352 case MAGIC_TYPE_ULEQLDATE:
353 case MAGIC_TYPE_LELONG:
354 case MAGIC_TYPE_ULELONG:
355 case MAGIC_TYPE_LEFLOAT:
356 case MAGIC_TYPE_LEDATE:
357 case MAGIC_TYPE_LELDATE:
358 case MAGIC_TYPE_ULEDATE:
359 case MAGIC_TYPE_ULELDATE:
360 case MAGIC_TYPE_MELONG:
361 case MAGIC_TYPE_MEDATE:
362 case MAGIC_TYPE_MELDATE:
363 n += 8 * MAGIC_STRENGTH_MULTIPLIER10;
364 break;
365 case MAGIC_TYPE_STRING:
366 case MAGIC_TYPE_PSTRING:
367 n += ml->test_string_size * MAGIC_STRENGTH_MULTIPLIER10;
368 break;
369 case MAGIC_TYPE_BESTRING16:
370 case MAGIC_TYPE_LESTRING16:
371 n += ml->test_string_size * MAGIC_STRENGTH_MULTIPLIER10 / 2;
372 break;
373 case MAGIC_TYPE_REGEX:
374 case MAGIC_TYPE_SEARCH:
375 size = MAGIC_STRENGTH_MULTIPLIER10 / ml->test_string_size;
376 if (size < 1)
377 size = 1;
378 n += ml->test_string_size * size;
379 break;
380 }
381 switch (ml->test_operator) {
382 case '=':
383 n += MAGIC_STRENGTH_MULTIPLIER10;
384 break;
385 case '<':
386 case '>':
387 case '[':
388 case ']':
389 n -= 2 * MAGIC_STRENGTH_MULTIPLIER10;
390 break;
391 case '^':
392 case '&':
393 n -= MAGIC_STRENGTH_MULTIPLIER10;
394 break;
395 }
396
397skip:
398 switch (ml->strength_operator) {
399 case '+':
400 n += ml->strength_value;
401 break;
402 case '-':
403 n -= ml->strength_value;
404 break;
405 case '*':
406 n *= ml->strength_value;
407 break;
408 case '/':
409 n /= ml->strength_value;
410 break;
411 }
412 return (n <= 0 ? 1 : n);
413}
414
415static int
416magic_get_string(char **line, char *out, size_t *outlen)
417{
418 char *start, *cp, c;
419 int d0, d1, d2;
420
421 start = out;
422 for (cp = *line; *cp != '\0' && !isspace((u_char)*cp); cp++) {
423 if (*cp != '\\') {
424 *out++ = *cp;
425 continue;
426 }
427
428 switch (c = *++cp) {
429 case '\0': /* end of line */
430 return (-1);
431 case ' ':
432 *out++ = ' ';
433 break;
434 case '0':
435 case '1':
436 case '2':
437 case '3':
438 case '4':
439 case '5':
440 case '6':
441 case '7':
442 d0 = magic_odigit(cp[0]);
443 if (cp[0] != '\0')
444 d1 = magic_odigit(cp[1]);
445 else
446 d1 = -1;
447 if (cp[0] != '\0' && cp[1] != '\0')
448 d2 = magic_odigit(cp[2]);
449 else
450 d2 = -1;
451
452 if (d0 != -1 && d1 != -1 && d2 != -1) {
453 *out = d2 | (d1 << 3) | (d0 << 6);
454 cp += 2;
455 } else if (d0 != -1 && d1 != -1) {
456 *out = d1 | (d0 << 3);
457 cp++;
458 } else if (d0 != -1)
459 *out = d0;
460 else
461 return (-1);
462 out++;
463 break;
464 case 'x':
465 d0 = magic_xdigit(cp[1]);
466 if (cp[1] != '\0')
467 d1 = magic_xdigit(cp[2]);
468 else
469 d1 = -1;
470
471 if (d0 != -1 && d1 != -1) {
472 *out = d1 | (d0 << 4);
473 cp += 2;
474 } else if (d0 != -1) {
475 *out = d0;
476 cp++;
477 } else
478 return (-1);
479 out++;
480
481 break;
482 case 'a':
483 *out++ = '\a';
484 break;
485 case 'b':
486 *out++ = '\b';
487 break;
488 case 't':
489 *out++ = '\t';
490 break;
491 case 'f':
492 *out++ = '\f';
493 break;
494 case 'n':
495 *out++ = '\n';
496 break;
497 case 'r':
498 *out++ = '\r';
499 break;
500 case '\\':
501 *out++ = '\\';
502 break;
503 case '\'':
504 *out++ = '\'';
505 break;
506 case '\"':
507 *out++ = '\"';
508 break;
509 default:
510 *out++ = c;
511 break;
512 }
513 }
514 *out = '\0';
515 *outlen = out - start;
516
517 *line = cp;
518 return (0);
519}
520
521static int
522magic_parse_offset(struct magic_line *ml, char **line)
523{
524 char *copy, *s, *cp, *endptr;
525
526 while (isspace((u_char)**line))
527 (*line)++;
528 copy = s = cp = xmalloc(strlen(*line) + 1);
529 while (**line != '\0' && !isspace((u_char)**line))
530 *cp++ = *(*line)++;
531 *cp = '\0';
532
533 ml->offset = 0;
534 ml->offset_relative = 0;
535
536 ml->indirect_type = ' ';
537 ml->indirect_relative = 0;
538 ml->indirect_offset = 0;
539 ml->indirect_operator = ' ';
540 ml->indirect_operand = 0;
541
542 if (*s == '&') {
543 ml->offset_relative = 1;
544 s++;
545 }
546
547 if (*s != '(') {
548 endptr = magic_strtoll(s, &ml->offset);
549 if (endptr == NULL((void *)0) || *endptr != '\0') {
550 magic_warn(ml, "missing closing bracket");
551 goto fail;
552 }
553 if (ml->offset < 0 && !ml->offset_relative) {
554 magic_warn(ml, "negative absolute offset");
555 goto fail;
556 }
557 goto done;
558 }
559 s++;
560
561 if (*s == '&') {
562 ml->indirect_relative = 1;
563 s++;
564 }
565
566 endptr = magic_strtoll(s, &ml->indirect_offset);
567 if (endptr == NULL((void *)0)) {
568 magic_warn(ml, "can't parse offset: %s", s);
569 goto fail;
570 }
571 s = endptr;
572 if (*s == ')')
573 goto done;
574
575 if (*s == '.') {
576 s++;
577 if (*s == '\0' || strchr("bslBSL", *s) == NULL((void *)0)) {
578 magic_warn(ml, "unknown offset type: %c", *s);
579 goto fail;
580 }
581 ml->indirect_type = *s;
582 s++;
583 if (*s == ')')
584 goto done;
585 }
586
587 if (*s == '\0' || strchr("+-*", *s) == NULL((void *)0)) {
588 magic_warn(ml, "unknown offset operator: %c", *s);
589 goto fail;
590 }
591 ml->indirect_operator = *s;
592 s++;
593 if (*s == ')')
594 goto done;
595
596 if (*s == '(') {
597 s++;
598 endptr = magic_strtoll(s, &ml->indirect_operand);
599 if (endptr == NULL((void *)0) || *endptr != ')') {
600 magic_warn(ml, "missing closing bracket");
601 goto fail;
602 }
603 if (*++endptr != ')') {
604 magic_warn(ml, "missing closing bracket");
605 goto fail;
606 }
607 } else {
608 endptr = magic_strtoll(s, &ml->indirect_operand);
609 if (endptr == NULL((void *)0) || *endptr != ')') {
610 magic_warn(ml, "missing closing bracket");
611 goto fail;
612 }
613 }
614
615done:
616 free(copy);
617 return (0);
618
619fail:
620 free(copy);
621 return (-1);
622}
623
624static int
625magic_parse_type(struct magic_line *ml, char **line)
626{
627 char *copy, *s, *cp, *endptr;
628
629 while (isspace((u_char)**line))
630 (*line)++;
631 copy = s = cp = xmalloc(strlen(*line) + 1);
632 while (**line != '\0' && !isspace((u_char)**line))
633 *cp++ = *(*line)++;
634 *cp = '\0';
635
636 ml->type = MAGIC_TYPE_NONE;
637 ml->type_operator = ' ';
638 ml->type_operand = 0;
639
640 if (strcmp(s, "name") == 0) {
641 ml->type = MAGIC_TYPE_NAME;
642 ml->type_string = xstrdup(s);
643 goto done;
644 }
645 if (strcmp(s, "use") == 0) {
646 ml->type = MAGIC_TYPE_USE;
647 ml->type_string = xstrdup(s);
648 goto done;
649 }
650
651 if (strncmp(s, "string", (sizeof "string") - 1) == 0 ||
652 strncmp(s, "ustring", (sizeof "ustring") - 1) == 0) {
653 if (*s == 'u')
654 ml->type_string = xstrdup(s + 1);
655 else
656 ml->type_string = xstrdup(s);
657 ml->type = MAGIC_TYPE_STRING;
658 magic_mark_text(ml, 0);
659 goto done;
660 }
661 if (strncmp(s, "pstring", (sizeof "pstring") - 1) == 0 ||
662 strncmp(s, "upstring", (sizeof "upstring") - 1) == 0) {
663 if (*s == 'u')
664 ml->type_string = xstrdup(s + 1);
665 else
666 ml->type_string = xstrdup(s);
667 ml->type = MAGIC_TYPE_PSTRING;
668 magic_mark_text(ml, 0);
669 goto done;
670 }
671 if (strncmp(s, "search", (sizeof "search") - 1) == 0 ||
672 strncmp(s, "usearch", (sizeof "usearch") - 1) == 0) {
673 if (*s == 'u')
674 ml->type_string = xstrdup(s + 1);
675 else
676 ml->type_string = xstrdup(s);
677 ml->type = MAGIC_TYPE_SEARCH;
678 goto done;
679 }
680 if (strncmp(s, "regex", (sizeof "regex") - 1) == 0 ||
681 strncmp(s, "uregex", (sizeof "uregex") - 1) == 0) {
682 if (*s == 'u')
683 ml->type_string = xstrdup(s + 1);
684 else
685 ml->type_string = xstrdup(s);
686 ml->type = MAGIC_TYPE_REGEX;
687 goto done;
688 }
689 ml->type_string = xstrdup(s);
690
691 cp = &s[strcspn(s, "+-&/%*")];
692 if (*cp != '\0') {
693 ml->type_operator = *cp;
694 endptr = magic_strtoull(cp + 1, &ml->type_operand);
695 if (endptr == NULL((void *)0) || *endptr != '\0') {
696 magic_warn(ml, "can't parse operand: %s", cp + 1);
697 goto fail;
698 }
699 *cp = '\0';
700 }
701
702 if (strcmp(s, "byte") == 0)
703 ml->type = MAGIC_TYPE_BYTE;
704 else if (strcmp(s, "short") == 0)
705 ml->type = MAGIC_TYPE_SHORT;
706 else if (strcmp(s, "long") == 0)
707 ml->type = MAGIC_TYPE_LONG;
708 else if (strcmp(s, "quad") == 0)
709 ml->type = MAGIC_TYPE_QUAD;
710 else if (strcmp(s, "ubyte") == 0)
711 ml->type = MAGIC_TYPE_UBYTE;
712 else if (strcmp(s, "ushort") == 0)
713 ml->type = MAGIC_TYPE_USHORT;
714 else if (strcmp(s, "ulong") == 0)
715 ml->type = MAGIC_TYPE_ULONG;
716 else if (strcmp(s, "uquad") == 0)
717 ml->type = MAGIC_TYPE_UQUAD;
718 else if (strcmp(s, "float") == 0 || strcmp(s, "ufloat") == 0)
719 ml->type = MAGIC_TYPE_FLOAT;
720 else if (strcmp(s, "double") == 0 || strcmp(s, "udouble") == 0)
721 ml->type = MAGIC_TYPE_DOUBLE;
722 else if (strcmp(s, "date") == 0)
723 ml->type = MAGIC_TYPE_DATE;
724 else if (strcmp(s, "qdate") == 0)
725 ml->type = MAGIC_TYPE_QDATE;
726 else if (strcmp(s, "ldate") == 0)
727 ml->type = MAGIC_TYPE_LDATE;
728 else if (strcmp(s, "qldate") == 0)
729 ml->type = MAGIC_TYPE_QLDATE;
730 else if (strcmp(s, "udate") == 0)
731 ml->type = MAGIC_TYPE_UDATE;
732 else if (strcmp(s, "uqdate") == 0)
733 ml->type = MAGIC_TYPE_UQDATE;
734 else if (strcmp(s, "uldate") == 0)
735 ml->type = MAGIC_TYPE_ULDATE;
736 else if (strcmp(s, "uqldate") == 0)
737 ml->type = MAGIC_TYPE_UQLDATE;
738 else if (strcmp(s, "beshort") == 0)
739 ml->type = MAGIC_TYPE_BESHORT;
740 else if (strcmp(s, "belong") == 0)
741 ml->type = MAGIC_TYPE_BELONG;
742 else if (strcmp(s, "bequad") == 0)
743 ml->type = MAGIC_TYPE_BEQUAD;
744 else if (strcmp(s, "ubeshort") == 0)
745 ml->type = MAGIC_TYPE_UBESHORT;
746 else if (strcmp(s, "ubelong") == 0)
747 ml->type = MAGIC_TYPE_UBELONG;
748 else if (strcmp(s, "ubequad") == 0)
749 ml->type = MAGIC_TYPE_UBEQUAD;
750 else if (strcmp(s, "befloat") == 0 || strcmp(s, "ubefloat") == 0)
751 ml->type = MAGIC_TYPE_BEFLOAT;
752 else if (strcmp(s, "bedouble") == 0 || strcmp(s, "ubedouble") == 0)
753 ml->type = MAGIC_TYPE_BEDOUBLE;
754 else if (strcmp(s, "bedate") == 0)
755 ml->type = MAGIC_TYPE_BEDATE;
756 else if (strcmp(s, "beqdate") == 0)
757 ml->type = MAGIC_TYPE_BEQDATE;
758 else if (strcmp(s, "beldate") == 0)
759 ml->type = MAGIC_TYPE_BELDATE;
760 else if (strcmp(s, "beqldate") == 0)
761 ml->type = MAGIC_TYPE_BEQLDATE;
762 else if (strcmp(s, "ubedate") == 0)
763 ml->type = MAGIC_TYPE_UBEDATE;
764 else if (strcmp(s, "ubeqdate") == 0)
765 ml->type = MAGIC_TYPE_UBEQDATE;
766 else if (strcmp(s, "ubeldate") == 0)
767 ml->type = MAGIC_TYPE_UBELDATE;
768 else if (strcmp(s, "ubeqldate") == 0)
769 ml->type = MAGIC_TYPE_UBEQLDATE;
770 else if (strcmp(s, "bestring16") == 0 || strcmp(s, "ubestring16") == 0)
771 ml->type = MAGIC_TYPE_BESTRING16;
772 else if (strcmp(s, "leshort") == 0)
773 ml->type = MAGIC_TYPE_LESHORT;
774 else if (strcmp(s, "lelong") == 0)
775 ml->type = MAGIC_TYPE_LELONG;
776 else if (strcmp(s, "lequad") == 0)
777 ml->type = MAGIC_TYPE_LEQUAD;
778 else if (strcmp(s, "uleshort") == 0)
779 ml->type = MAGIC_TYPE_ULESHORT;
780 else if (strcmp(s, "ulelong") == 0)
781 ml->type = MAGIC_TYPE_ULELONG;
782 else if (strcmp(s, "ulequad") == 0)
783 ml->type = MAGIC_TYPE_ULEQUAD;
784 else if (strcmp(s, "lefloat") == 0 || strcmp(s, "ulefloat") == 0)
785 ml->type = MAGIC_TYPE_LEFLOAT;
786 else if (strcmp(s, "ledouble") == 0 || strcmp(s, "uledouble") == 0)
787 ml->type = MAGIC_TYPE_LEDOUBLE;
788 else if (strcmp(s, "ledate") == 0)
789 ml->type = MAGIC_TYPE_LEDATE;
790 else if (strcmp(s, "leqdate") == 0)
791 ml->type = MAGIC_TYPE_LEQDATE;
792 else if (strcmp(s, "leldate") == 0)
793 ml->type = MAGIC_TYPE_LELDATE;
794 else if (strcmp(s, "leqldate") == 0)
795 ml->type = MAGIC_TYPE_LEQLDATE;
796 else if (strcmp(s, "uledate") == 0)
797 ml->type = MAGIC_TYPE_ULEDATE;
798 else if (strcmp(s, "uleqdate") == 0)
799 ml->type = MAGIC_TYPE_ULEQDATE;
800 else if (strcmp(s, "uleldate") == 0)
801 ml->type = MAGIC_TYPE_ULELDATE;
802 else if (strcmp(s, "uleqldate") == 0)
803 ml->type = MAGIC_TYPE_ULEQLDATE;
804 else if (strcmp(s, "lestring16") == 0 || strcmp(s, "ulestring16") == 0)
805 ml->type = MAGIC_TYPE_LESTRING16;
806 else if (strcmp(s, "melong") == 0 || strcmp(s, "umelong") == 0)
807 ml->type = MAGIC_TYPE_MELONG;
808 else if (strcmp(s, "medate") == 0 || strcmp(s, "umedate") == 0)
809 ml->type = MAGIC_TYPE_MEDATE;
810 else if (strcmp(s, "meldate") == 0 || strcmp(s, "umeldate") == 0)
811 ml->type = MAGIC_TYPE_MELDATE;
812 else if (strcmp(s, "default") == 0 || strcmp(s, "udefault") == 0)
813 ml->type = MAGIC_TYPE_DEFAULT;
814 else if (strcmp(s, "clear") == 0 || strcmp(s, "uclear") == 0)
815 ml->type = MAGIC_TYPE_CLEAR;
816 else {
817 magic_warn(ml, "unknown type: %s", s);
818 goto fail;
819 }
820 magic_mark_text(ml, 0);
821
822done:
823 free(copy);
824 return (0);
825
826fail:
827 free(copy);
828 return (-1);
829}
830
831static int
832magic_parse_value(struct magic_line *ml, char **line)
833{
834 char *copy, *s, *cp, *endptr;
835 size_t slen;
836 uint64_t u;
837
838 while (isspace((u_char)**line))
839 (*line)++;
840
841 ml->test_operator = '=';
842 ml->test_not = 0;
843 ml->test_string = NULL((void *)0);
844 ml->test_string_size = 0;
845 ml->test_unsigned = 0;
846 ml->test_signed = 0;
847
848 if (**line == '\0')
849 return (0);
850
851 s = *line;
852 if (s[0] == 'x' && (s[1] == '\0' || isspace((u_char)s[1]))) {
853 (*line)++;
854 ml->test_operator = 'x';
855 return (0);
856 }
857
858 if (ml->type == MAGIC_TYPE_DEFAULT || ml->type == MAGIC_TYPE_CLEAR) {
859 magic_warn(ml, "test specified for default or clear");
860 ml->test_operator = 'x';
861 return (0);
862 }
863
864 if (**line == '!') {
865 ml->test_not = 1;
866 (*line)++;
867 }
868
869 switch (ml->type) {
870 case MAGIC_TYPE_NAME:
871 case MAGIC_TYPE_USE:
872 copy = s = xmalloc(strlen(*line) + 1);
873 if (magic_get_string(line, s, &slen) != 0 || slen == 0) {
874 magic_warn(ml, "can't parse string");
875 goto fail;
876 }
877 if (slen == 0 || *s == '\0' || strcmp(s, "^") == 0) {
878 magic_warn(ml, "invalid name");
879 goto fail;
880 }
881 ml->name = s;
882 return (0); /* do not free */
883 case MAGIC_TYPE_STRING:
884 case MAGIC_TYPE_PSTRING:
885 case MAGIC_TYPE_SEARCH:
886 if (**line == '>' || **line == '<' || **line == '=') {
887 ml->test_operator = **line;
888 (*line)++;
889 }
890 /* FALLTHROUGH */
891 case MAGIC_TYPE_REGEX:
892 if (**line == '=')
893 (*line)++;
894 copy = s = xmalloc(strlen(*line) + 1);
895 if (magic_get_string(line, s, &slen) != 0) {
896 magic_warn(ml, "can't parse string");
897 goto fail;
898 }
899 ml->test_string_size = slen;
900 ml->test_string = s;
901 return (0); /* do not free */
902 default:
903 break;
904 }
905
906 while (isspace((u_char)**line))
907 (*line)++;
908 if ((*line)[0] == '<' && (*line)[1] == '=') {
909 ml->test_operator = '[';
910 (*line) += 2;
911 } else if ((*line)[0] == '>' && (*line)[1] == '=') {
912 ml->test_operator = ']';
913 (*line) += 2;
914 } else if (**line != '\0' && strchr("=<>&^", **line) != NULL((void *)0)) {
915 ml->test_operator = **line;
916 (*line)++;
917 }
918
919 while (isspace((u_char)**line))
920 (*line)++;
921 copy = cp = xmalloc(strlen(*line) + 1);
922 while (**line != '\0' && !isspace((u_char)**line))
923 *cp++ = *(*line)++;
924 *cp = '\0';
925
926 switch (ml->type) {
927 case MAGIC_TYPE_FLOAT:
928 case MAGIC_TYPE_DOUBLE:
929 case MAGIC_TYPE_BEFLOAT:
930 case MAGIC_TYPE_BEDOUBLE:
931 case MAGIC_TYPE_LEFLOAT:
932 case MAGIC_TYPE_LEDOUBLE:
933 errno(*__errno()) = 0;
934 ml->test_double = strtod(copy, &endptr);
935 if (errno(*__errno()) == ERANGE34)
936 endptr = NULL((void *)0);
937 break;
938 default:
939 if (*ml->type_string == 'u')
940 endptr = magic_strtoull(copy, &ml->test_unsigned);
941 else {
942 endptr = magic_strtoll(copy, &ml->test_signed);
943 if (endptr == NULL((void *)0) || *endptr != '\0') {
944 /*
945 * If we can't parse this as a signed number,
946 * try as unsigned instead.
947 */
948 endptr = magic_strtoull(copy, &u);
949 if (endptr != NULL((void *)0) && *endptr == '\0')
950 ml->test_signed = (int64_t)u;
951 }
952 }
953 break;
954 }
955 if (endptr == NULL((void *)0) || *endptr != '\0') {
956 magic_warn(ml, "can't parse number: %s", copy);
957 goto fail;
958 }
959
960 free(copy);
961 return (0);
962
963fail:
964 free(copy);
965 return (-1);
966}
967
968int
969magic_compare(struct magic_line *ml1, struct magic_line *ml2)
970{
971 if (ml1->strength < ml2->strength)
972 return (1);
973 if (ml1->strength > ml2->strength)
974 return (-1);
975
976 /*
977 * The original file depends on the (undefined!) qsort(3) behaviour
978 * when the strength is equal. This is impossible to reproduce with an
979 * RB tree so just use the line number and hope for the best.
980 */
981 if (ml1->line < ml2->line)
982 return (-1);
983 if (ml1->line > ml2->line)
984 return (1);
985
986 return (0);
987}
988RB_GENERATE(magic_tree, magic_line, node, magic_compare)void magic_tree_RB_INSERT_COLOR(struct magic_tree *head, struct
magic_line *elm) { struct magic_line *parent, *gparent, *tmp
; while ((parent = (elm)->node.rbe_parent) && (parent
)->node.rbe_color == 1) { gparent = (parent)->node.rbe_parent
; if (parent == (gparent)->node.rbe_left) { tmp = (gparent
)->node.rbe_right; if (tmp && (tmp)->node.rbe_color
== 1) { (tmp)->node.rbe_color = 0; do { (parent)->node
.rbe_color = 0; (gparent)->node.rbe_color = 1; } while (0)
; elm = gparent; continue; } if ((parent)->node.rbe_right ==
elm) { do { (tmp) = (parent)->node.rbe_right; if (((parent
)->node.rbe_right = (tmp)->node.rbe_left)) { ((tmp)->
node.rbe_left)->node.rbe_parent = (parent); } do {} while (
0); if (((tmp)->node.rbe_parent = (parent)->node.rbe_parent
)) { if ((parent) == ((parent)->node.rbe_parent)->node.
rbe_left) ((parent)->node.rbe_parent)->node.rbe_left = (
tmp); else ((parent)->node.rbe_parent)->node.rbe_right =
(tmp); } else (head)->rbh_root = (tmp); (tmp)->node.rbe_left
= (parent); (parent)->node.rbe_parent = (tmp); do {} while
(0); if (((tmp)->node.rbe_parent)) do {} while (0); } while
(0); tmp = parent; parent = elm; elm = tmp; } do { (parent)->
node.rbe_color = 0; (gparent)->node.rbe_color = 1; } while
(0); do { (tmp) = (gparent)->node.rbe_left; if (((gparent
)->node.rbe_left = (tmp)->node.rbe_right)) { ((tmp)->
node.rbe_right)->node.rbe_parent = (gparent); } do {} while
(0); if (((tmp)->node.rbe_parent = (gparent)->node.rbe_parent
)) { if ((gparent) == ((gparent)->node.rbe_parent)->node
.rbe_left) ((gparent)->node.rbe_parent)->node.rbe_left =
(tmp); else ((gparent)->node.rbe_parent)->node.rbe_right
= (tmp); } else (head)->rbh_root = (tmp); (tmp)->node.
rbe_right = (gparent); (gparent)->node.rbe_parent = (tmp);
do {} while (0); if (((tmp)->node.rbe_parent)) do {} while
(0); } while (0); } else { tmp = (gparent)->node.rbe_left
; if (tmp && (tmp)->node.rbe_color == 1) { (tmp)->
node.rbe_color = 0; do { (parent)->node.rbe_color = 0; (gparent
)->node.rbe_color = 1; } while (0); elm = gparent; continue
; } if ((parent)->node.rbe_left == elm) { do { (tmp) = (parent
)->node.rbe_left; if (((parent)->node.rbe_left = (tmp)->
node.rbe_right)) { ((tmp)->node.rbe_right)->node.rbe_parent
= (parent); } do {} while (0); if (((tmp)->node.rbe_parent
= (parent)->node.rbe_parent)) { if ((parent) == ((parent)
->node.rbe_parent)->node.rbe_left) ((parent)->node.rbe_parent
)->node.rbe_left = (tmp); else ((parent)->node.rbe_parent
)->node.rbe_right = (tmp); } else (head)->rbh_root = (tmp
); (tmp)->node.rbe_right = (parent); (parent)->node.rbe_parent
= (tmp); do {} while (0); if (((tmp)->node.rbe_parent)) do
{} while (0); } while (0); tmp = parent; parent = elm; elm =
tmp; } do { (parent)->node.rbe_color = 0; (gparent)->node
.rbe_color = 1; } while (0); do { (tmp) = (gparent)->node.
rbe_right; if (((gparent)->node.rbe_right = (tmp)->node
.rbe_left)) { ((tmp)->node.rbe_left)->node.rbe_parent =
(gparent); } do {} while (0); if (((tmp)->node.rbe_parent
= (gparent)->node.rbe_parent)) { if ((gparent) == ((gparent
)->node.rbe_parent)->node.rbe_left) ((gparent)->node
.rbe_parent)->node.rbe_left = (tmp); else ((gparent)->node
.rbe_parent)->node.rbe_right = (tmp); } else (head)->rbh_root
= (tmp); (tmp)->node.rbe_left = (gparent); (gparent)->
node.rbe_parent = (tmp); do {} while (0); if (((tmp)->node
.rbe_parent)) do {} while (0); } while (0); } } (head->rbh_root
)->node.rbe_color = 0; } void magic_tree_RB_REMOVE_COLOR(struct
magic_tree *head, struct magic_line *parent, struct magic_line
*elm) { struct magic_line *tmp; while ((elm == ((void *)0) ||
(elm)->node.rbe_color == 0) && elm != (head)->
rbh_root) { if ((parent)->node.rbe_left == elm) { tmp = (parent
)->node.rbe_right; if ((tmp)->node.rbe_color == 1) { do
{ (tmp)->node.rbe_color = 0; (parent)->node.rbe_color =
1; } while (0); do { (tmp) = (parent)->node.rbe_right; if
(((parent)->node.rbe_right = (tmp)->node.rbe_left)) { (
(tmp)->node.rbe_left)->node.rbe_parent = (parent); } do
{} while (0); if (((tmp)->node.rbe_parent = (parent)->
node.rbe_parent)) { if ((parent) == ((parent)->node.rbe_parent
)->node.rbe_left) ((parent)->node.rbe_parent)->node.
rbe_left = (tmp); else ((parent)->node.rbe_parent)->node
.rbe_right = (tmp); } else (head)->rbh_root = (tmp); (tmp)
->node.rbe_left = (parent); (parent)->node.rbe_parent =
(tmp); do {} while (0); if (((tmp)->node.rbe_parent)) do {
} while (0); } while (0); tmp = (parent)->node.rbe_right; }
if (((tmp)->node.rbe_left == ((void *)0) || ((tmp)->node
.rbe_left)->node.rbe_color == 0) && ((tmp)->node
.rbe_right == ((void *)0) || ((tmp)->node.rbe_right)->node
.rbe_color == 0)) { (tmp)->node.rbe_color = 1; elm = parent
; parent = (elm)->node.rbe_parent; } else { if ((tmp)->
node.rbe_right == ((void *)0) || ((tmp)->node.rbe_right)->
node.rbe_color == 0) { struct magic_line *oleft; if ((oleft =
(tmp)->node.rbe_left)) (oleft)->node.rbe_color = 0; (tmp
)->node.rbe_color = 1; do { (oleft) = (tmp)->node.rbe_left
; if (((tmp)->node.rbe_left = (oleft)->node.rbe_right))
{ ((oleft)->node.rbe_right)->node.rbe_parent = (tmp); }
do {} while (0); if (((oleft)->node.rbe_parent = (tmp)->
node.rbe_parent)) { if ((tmp) == ((tmp)->node.rbe_parent)->
node.rbe_left) ((tmp)->node.rbe_parent)->node.rbe_left =
(oleft); else ((tmp)->node.rbe_parent)->node.rbe_right
= (oleft); } else (head)->rbh_root = (oleft); (oleft)->
node.rbe_right = (tmp); (tmp)->node.rbe_parent = (oleft); do
{} while (0); if (((oleft)->node.rbe_parent)) do {} while
(0); } while (0); tmp = (parent)->node.rbe_right; } (tmp)
->node.rbe_color = (parent)->node.rbe_color; (parent)->
node.rbe_color = 0; if ((tmp)->node.rbe_right) ((tmp)->
node.rbe_right)->node.rbe_color = 0; do { (tmp) = (parent)
->node.rbe_right; if (((parent)->node.rbe_right = (tmp)
->node.rbe_left)) { ((tmp)->node.rbe_left)->node.rbe_parent
= (parent); } do {} while (0); if (((tmp)->node.rbe_parent
= (parent)->node.rbe_parent)) { if ((parent) == ((parent)
->node.rbe_parent)->node.rbe_left) ((parent)->node.rbe_parent
)->node.rbe_left = (tmp); else ((parent)->node.rbe_parent
)->node.rbe_right = (tmp); } else (head)->rbh_root = (tmp
); (tmp)->node.rbe_left = (parent); (parent)->node.rbe_parent
= (tmp); do {} while (0); if (((tmp)->node.rbe_parent)) do
{} while (0); } while (0); elm = (head)->rbh_root; break;
} } else { tmp = (parent)->node.rbe_left; if ((tmp)->node
.rbe_color == 1) { do { (tmp)->node.rbe_color = 0; (parent
)->node.rbe_color = 1; } while (0); do { (tmp) = (parent)->
node.rbe_left; if (((parent)->node.rbe_left = (tmp)->node
.rbe_right)) { ((tmp)->node.rbe_right)->node.rbe_parent
= (parent); } do {} while (0); if (((tmp)->node.rbe_parent
= (parent)->node.rbe_parent)) { if ((parent) == ((parent)
->node.rbe_parent)->node.rbe_left) ((parent)->node.rbe_parent
)->node.rbe_left = (tmp); else ((parent)->node.rbe_parent
)->node.rbe_right = (tmp); } else (head)->rbh_root = (tmp
); (tmp)->node.rbe_right = (parent); (parent)->node.rbe_parent
= (tmp); do {} while (0); if (((tmp)->node.rbe_parent)) do
{} while (0); } while (0); tmp = (parent)->node.rbe_left;
} if (((tmp)->node.rbe_left == ((void *)0) || ((tmp)->
node.rbe_left)->node.rbe_color == 0) && ((tmp)->
node.rbe_right == ((void *)0) || ((tmp)->node.rbe_right)->
node.rbe_color == 0)) { (tmp)->node.rbe_color = 1; elm = parent
; parent = (elm)->node.rbe_parent; } else { if ((tmp)->
node.rbe_left == ((void *)0) || ((tmp)->node.rbe_left)->
node.rbe_color == 0) { struct magic_line *oright; if ((oright
= (tmp)->node.rbe_right)) (oright)->node.rbe_color = 0
; (tmp)->node.rbe_color = 1; do { (oright) = (tmp)->node
.rbe_right; if (((tmp)->node.rbe_right = (oright)->node
.rbe_left)) { ((oright)->node.rbe_left)->node.rbe_parent
= (tmp); } do {} while (0); if (((oright)->node.rbe_parent
= (tmp)->node.rbe_parent)) { if ((tmp) == ((tmp)->node
.rbe_parent)->node.rbe_left) ((tmp)->node.rbe_parent)->
node.rbe_left = (oright); else ((tmp)->node.rbe_parent)->
node.rbe_right = (oright); } else (head)->rbh_root = (oright
); (oright)->node.rbe_left = (tmp); (tmp)->node.rbe_parent
= (oright); do {} while (0); if (((oright)->node.rbe_parent
)) do {} while (0); } while (0); tmp = (parent)->node.rbe_left
; } (tmp)->node.rbe_color = (parent)->node.rbe_color; (
parent)->node.rbe_color = 0; if ((tmp)->node.rbe_left) (
(tmp)->node.rbe_left)->node.rbe_color = 0; do { (tmp) =
(parent)->node.rbe_left; if (((parent)->node.rbe_left =
(tmp)->node.rbe_right)) { ((tmp)->node.rbe_right)->
node.rbe_parent = (parent); } do {} while (0); if (((tmp)->
node.rbe_parent = (parent)->node.rbe_parent)) { if ((parent
) == ((parent)->node.rbe_parent)->node.rbe_left) ((parent
)->node.rbe_parent)->node.rbe_left = (tmp); else ((parent
)->node.rbe_parent)->node.rbe_right = (tmp); } else (head
)->rbh_root = (tmp); (tmp)->node.rbe_right = (parent); (
parent)->node.rbe_parent = (tmp); do {} while (0); if (((tmp
)->node.rbe_parent)) do {} while (0); } while (0); elm = (
head)->rbh_root; break; } } } if (elm) (elm)->node.rbe_color
= 0; } struct magic_line * magic_tree_RB_REMOVE(struct magic_tree
*head, struct magic_line *elm) { struct magic_line *child, *
parent, *old = elm; int color; if ((elm)->node.rbe_left ==
((void *)0)) child = (elm)->node.rbe_right; else if ((elm
)->node.rbe_right == ((void *)0)) child = (elm)->node.rbe_left
; else { struct magic_line *left; elm = (elm)->node.rbe_right
; while ((left = (elm)->node.rbe_left)) elm = left; child =
(elm)->node.rbe_right; parent = (elm)->node.rbe_parent
; color = (elm)->node.rbe_color; if (child) (child)->node
.rbe_parent = parent; if (parent) { if ((parent)->node.rbe_left
== elm) (parent)->node.rbe_left = child; else (parent)->
node.rbe_right = child; do {} while (0); } else (head)->rbh_root
= child; if ((elm)->node.rbe_parent == old) parent = elm;
(elm)->node = (old)->node; if ((old)->node.rbe_parent
) { if (((old)->node.rbe_parent)->node.rbe_left == old)
((old)->node.rbe_parent)->node.rbe_left = elm; else ((
old)->node.rbe_parent)->node.rbe_right = elm; do {} while
(0); } else (head)->rbh_root = elm; ((old)->node.rbe_left
)->node.rbe_parent = elm; if ((old)->node.rbe_right) ((
old)->node.rbe_right)->node.rbe_parent = elm; if (parent
) { left = parent; do { do {} while (0); } while ((left = (left
)->node.rbe_parent)); } goto color; } parent = (elm)->node
.rbe_parent; color = (elm)->node.rbe_color; if (child) (child
)->node.rbe_parent = parent; if (parent) { if ((parent)->
node.rbe_left == elm) (parent)->node.rbe_left = child; else
(parent)->node.rbe_right = child; do {} while (0); } else
(head)->rbh_root = child; color: if (color == 0) magic_tree_RB_REMOVE_COLOR
(head, parent, child); return (old); } struct magic_line * magic_tree_RB_INSERT
(struct magic_tree *head, struct magic_line *elm) { struct magic_line
*tmp; struct magic_line *parent = ((void *)0); int comp = 0;
tmp = (head)->rbh_root; while (tmp) { parent = tmp; comp =
(magic_compare)(elm, parent); if (comp < 0) tmp = (tmp)->
node.rbe_left; else if (comp > 0) tmp = (tmp)->node.rbe_right
; else return (tmp); } do { (elm)->node.rbe_parent = parent
; (elm)->node.rbe_left = (elm)->node.rbe_right = ((void
*)0); (elm)->node.rbe_color = 1; } while (0); if (parent !=
((void *)0)) { if (comp < 0) (parent)->node.rbe_left =
elm; else (parent)->node.rbe_right = elm; do {} while (0)
; } else (head)->rbh_root = elm; magic_tree_RB_INSERT_COLOR
(head, elm); return (((void *)0)); } struct magic_line * magic_tree_RB_FIND
(struct magic_tree *head, struct magic_line *elm) { struct magic_line
*tmp = (head)->rbh_root; int comp; while (tmp) { comp = magic_compare
(elm, tmp); if (comp < 0) tmp = (tmp)->node.rbe_left; else
if (comp > 0) tmp = (tmp)->node.rbe_right; else return
(tmp); } return (((void *)0)); } struct magic_line * magic_tree_RB_NFIND
(struct magic_tree *head, struct magic_line *elm) { struct magic_line
*tmp = (head)->rbh_root; struct magic_line *res = ((void *
)0); int comp; while (tmp) { comp = magic_compare(elm, tmp); if
(comp < 0) { res = tmp; tmp = (tmp)->node.rbe_left; } else
if (comp > 0) tmp = (tmp)->node.rbe_right; else return
(tmp); } return (res); } struct magic_line * magic_tree_RB_NEXT
(struct magic_line *elm) { if ((elm)->node.rbe_right) { elm
= (elm)->node.rbe_right; while ((elm)->node.rbe_left) elm
= (elm)->node.rbe_left; } else { if ((elm)->node.rbe_parent
&& (elm == ((elm)->node.rbe_parent)->node.rbe_left
)) elm = (elm)->node.rbe_parent; else { while ((elm)->node
.rbe_parent && (elm == ((elm)->node.rbe_parent)->
node.rbe_right)) elm = (elm)->node.rbe_parent; elm = (elm)
->node.rbe_parent; } } return (elm); } struct magic_line *
magic_tree_RB_PREV(struct magic_line *elm) { if ((elm)->node
.rbe_left) { elm = (elm)->node.rbe_left; while ((elm)->
node.rbe_right) elm = (elm)->node.rbe_right; } else { if (
(elm)->node.rbe_parent && (elm == ((elm)->node.
rbe_parent)->node.rbe_right)) elm = (elm)->node.rbe_parent
; else { while ((elm)->node.rbe_parent && (elm == (
(elm)->node.rbe_parent)->node.rbe_left)) elm = (elm)->
node.rbe_parent; elm = (elm)->node.rbe_parent; } } return (
elm); } struct magic_line * magic_tree_RB_MINMAX(struct magic_tree
*head, int val) { struct magic_line *tmp = (head)->rbh_root
; struct magic_line *parent = ((void *)0); while (tmp) { parent
= tmp; if (val < 0) tmp = (tmp)->node.rbe_left; else tmp
= (tmp)->node.rbe_right; } return (parent); }
;
989
990int
991magic_named_compare(struct magic_line *ml1, struct magic_line *ml2)
992{
993 return (strcmp(ml1->name, ml2->name));
994}
995RB_GENERATE(magic_named_tree, magic_line, node, magic_named_compare)void magic_named_tree_RB_INSERT_COLOR(struct magic_named_tree
*head, struct magic_line *elm) { struct magic_line *parent, *
gparent, *tmp; while ((parent = (elm)->node.rbe_parent) &&
(parent)->node.rbe_color == 1) { gparent = (parent)->node
.rbe_parent; if (parent == (gparent)->node.rbe_left) { tmp
= (gparent)->node.rbe_right; if (tmp && (tmp)->
node.rbe_color == 1) { (tmp)->node.rbe_color = 0; do { (parent
)->node.rbe_color = 0; (gparent)->node.rbe_color = 1; }
while (0); elm = gparent; continue; } if ((parent)->node.
rbe_right == elm) { do { (tmp) = (parent)->node.rbe_right;
if (((parent)->node.rbe_right = (tmp)->node.rbe_left))
{ ((tmp)->node.rbe_left)->node.rbe_parent = (parent); }
do {} while (0); if (((tmp)->node.rbe_parent = (parent)->
node.rbe_parent)) { if ((parent) == ((parent)->node.rbe_parent
)->node.rbe_left) ((parent)->node.rbe_parent)->node.
rbe_left = (tmp); else ((parent)->node.rbe_parent)->node
.rbe_right = (tmp); } else (head)->rbh_root = (tmp); (tmp)
->node.rbe_left = (parent); (parent)->node.rbe_parent =
(tmp); do {} while (0); if (((tmp)->node.rbe_parent)) do {
} while (0); } while (0); tmp = parent; parent = elm; elm = tmp
; } do { (parent)->node.rbe_color = 0; (gparent)->node.
rbe_color = 1; } while (0); do { (tmp) = (gparent)->node.rbe_left
; if (((gparent)->node.rbe_left = (tmp)->node.rbe_right
)) { ((tmp)->node.rbe_right)->node.rbe_parent = (gparent
); } do {} while (0); if (((tmp)->node.rbe_parent = (gparent
)->node.rbe_parent)) { if ((gparent) == ((gparent)->node
.rbe_parent)->node.rbe_left) ((gparent)->node.rbe_parent
)->node.rbe_left = (tmp); else ((gparent)->node.rbe_parent
)->node.rbe_right = (tmp); } else (head)->rbh_root = (tmp
); (tmp)->node.rbe_right = (gparent); (gparent)->node.rbe_parent
= (tmp); do {} while (0); if (((tmp)->node.rbe_parent)) do
{} while (0); } while (0); } else { tmp = (gparent)->node
.rbe_left; if (tmp && (tmp)->node.rbe_color == 1) {
(tmp)->node.rbe_color = 0; do { (parent)->node.rbe_color
= 0; (gparent)->node.rbe_color = 1; } while (0); elm = gparent
; continue; } if ((parent)->node.rbe_left == elm) { do { (
tmp) = (parent)->node.rbe_left; if (((parent)->node.rbe_left
= (tmp)->node.rbe_right)) { ((tmp)->node.rbe_right)->
node.rbe_parent = (parent); } do {} while (0); if (((tmp)->
node.rbe_parent = (parent)->node.rbe_parent)) { if ((parent
) == ((parent)->node.rbe_parent)->node.rbe_left) ((parent
)->node.rbe_parent)->node.rbe_left = (tmp); else ((parent
)->node.rbe_parent)->node.rbe_right = (tmp); } else (head
)->rbh_root = (tmp); (tmp)->node.rbe_right = (parent); (
parent)->node.rbe_parent = (tmp); do {} while (0); if (((tmp
)->node.rbe_parent)) do {} while (0); } while (0); tmp = parent
; parent = elm; elm = tmp; } do { (parent)->node.rbe_color
= 0; (gparent)->node.rbe_color = 1; } while (0); do { (tmp
) = (gparent)->node.rbe_right; if (((gparent)->node.rbe_right
= (tmp)->node.rbe_left)) { ((tmp)->node.rbe_left)->
node.rbe_parent = (gparent); } do {} while (0); if (((tmp)->
node.rbe_parent = (gparent)->node.rbe_parent)) { if ((gparent
) == ((gparent)->node.rbe_parent)->node.rbe_left) ((gparent
)->node.rbe_parent)->node.rbe_left = (tmp); else ((gparent
)->node.rbe_parent)->node.rbe_right = (tmp); } else (head
)->rbh_root = (tmp); (tmp)->node.rbe_left = (gparent); (
gparent)->node.rbe_parent = (tmp); do {} while (0); if (((
tmp)->node.rbe_parent)) do {} while (0); } while (0); } } (
head->rbh_root)->node.rbe_color = 0; } void magic_named_tree_RB_REMOVE_COLOR
(struct magic_named_tree *head, struct magic_line *parent, struct
magic_line *elm) { struct magic_line *tmp; while ((elm == ((
void *)0) || (elm)->node.rbe_color == 0) && elm !=
(head)->rbh_root) { if ((parent)->node.rbe_left == elm
) { tmp = (parent)->node.rbe_right; if ((tmp)->node.rbe_color
== 1) { do { (tmp)->node.rbe_color = 0; (parent)->node
.rbe_color = 1; } while (0); do { (tmp) = (parent)->node.rbe_right
; if (((parent)->node.rbe_right = (tmp)->node.rbe_left)
) { ((tmp)->node.rbe_left)->node.rbe_parent = (parent);
} do {} while (0); if (((tmp)->node.rbe_parent = (parent)
->node.rbe_parent)) { if ((parent) == ((parent)->node.rbe_parent
)->node.rbe_left) ((parent)->node.rbe_parent)->node.
rbe_left = (tmp); else ((parent)->node.rbe_parent)->node
.rbe_right = (tmp); } else (head)->rbh_root = (tmp); (tmp)
->node.rbe_left = (parent); (parent)->node.rbe_parent =
(tmp); do {} while (0); if (((tmp)->node.rbe_parent)) do {
} while (0); } while (0); tmp = (parent)->node.rbe_right; }
if (((tmp)->node.rbe_left == ((void *)0) || ((tmp)->node
.rbe_left)->node.rbe_color == 0) && ((tmp)->node
.rbe_right == ((void *)0) || ((tmp)->node.rbe_right)->node
.rbe_color == 0)) { (tmp)->node.rbe_color = 1; elm = parent
; parent = (elm)->node.rbe_parent; } else { if ((tmp)->
node.rbe_right == ((void *)0) || ((tmp)->node.rbe_right)->
node.rbe_color == 0) { struct magic_line *oleft; if ((oleft =
(tmp)->node.rbe_left)) (oleft)->node.rbe_color = 0; (tmp
)->node.rbe_color = 1; do { (oleft) = (tmp)->node.rbe_left
; if (((tmp)->node.rbe_left = (oleft)->node.rbe_right))
{ ((oleft)->node.rbe_right)->node.rbe_parent = (tmp); }
do {} while (0); if (((oleft)->node.rbe_parent = (tmp)->
node.rbe_parent)) { if ((tmp) == ((tmp)->node.rbe_parent)->
node.rbe_left) ((tmp)->node.rbe_parent)->node.rbe_left =
(oleft); else ((tmp)->node.rbe_parent)->node.rbe_right
= (oleft); } else (head)->rbh_root = (oleft); (oleft)->
node.rbe_right = (tmp); (tmp)->node.rbe_parent = (oleft); do
{} while (0); if (((oleft)->node.rbe_parent)) do {} while
(0); } while (0); tmp = (parent)->node.rbe_right; } (tmp)
->node.rbe_color = (parent)->node.rbe_color; (parent)->
node.rbe_color = 0; if ((tmp)->node.rbe_right) ((tmp)->
node.rbe_right)->node.rbe_color = 0; do { (tmp) = (parent)
->node.rbe_right; if (((parent)->node.rbe_right = (tmp)
->node.rbe_left)) { ((tmp)->node.rbe_left)->node.rbe_parent
= (parent); } do {} while (0); if (((tmp)->node.rbe_parent
= (parent)->node.rbe_parent)) { if ((parent) == ((parent)
->node.rbe_parent)->node.rbe_left) ((parent)->node.rbe_parent
)->node.rbe_left = (tmp); else ((parent)->node.rbe_parent
)->node.rbe_right = (tmp); } else (head)->rbh_root = (tmp
); (tmp)->node.rbe_left = (parent); (parent)->node.rbe_parent
= (tmp); do {} while (0); if (((tmp)->node.rbe_parent)) do
{} while (0); } while (0); elm = (head)->rbh_root; break;
} } else { tmp = (parent)->node.rbe_left; if ((tmp)->node
.rbe_color == 1) { do { (tmp)->node.rbe_color = 0; (parent
)->node.rbe_color = 1; } while (0); do { (tmp) = (parent)->
node.rbe_left; if (((parent)->node.rbe_left = (tmp)->node
.rbe_right)) { ((tmp)->node.rbe_right)->node.rbe_parent
= (parent); } do {} while (0); if (((tmp)->node.rbe_parent
= (parent)->node.rbe_parent)) { if ((parent) == ((parent)
->node.rbe_parent)->node.rbe_left) ((parent)->node.rbe_parent
)->node.rbe_left = (tmp); else ((parent)->node.rbe_parent
)->node.rbe_right = (tmp); } else (head)->rbh_root = (tmp
); (tmp)->node.rbe_right = (parent); (parent)->node.rbe_parent
= (tmp); do {} while (0); if (((tmp)->node.rbe_parent)) do
{} while (0); } while (0); tmp = (parent)->node.rbe_left;
} if (((tmp)->node.rbe_left == ((void *)0) || ((tmp)->
node.rbe_left)->node.rbe_color == 0) && ((tmp)->
node.rbe_right == ((void *)0) || ((tmp)->node.rbe_right)->
node.rbe_color == 0)) { (tmp)->node.rbe_color = 1; elm = parent
; parent = (elm)->node.rbe_parent; } else { if ((tmp)->
node.rbe_left == ((void *)0) || ((tmp)->node.rbe_left)->
node.rbe_color == 0) { struct magic_line *oright; if ((oright
= (tmp)->node.rbe_right)) (oright)->node.rbe_color = 0
; (tmp)->node.rbe_color = 1; do { (oright) = (tmp)->node
.rbe_right; if (((tmp)->node.rbe_right = (oright)->node
.rbe_left)) { ((oright)->node.rbe_left)->node.rbe_parent
= (tmp); } do {} while (0); if (((oright)->node.rbe_parent
= (tmp)->node.rbe_parent)) { if ((tmp) == ((tmp)->node
.rbe_parent)->node.rbe_left) ((tmp)->node.rbe_parent)->
node.rbe_left = (oright); else ((tmp)->node.rbe_parent)->
node.rbe_right = (oright); } else (head)->rbh_root = (oright
); (oright)->node.rbe_left = (tmp); (tmp)->node.rbe_parent
= (oright); do {} while (0); if (((oright)->node.rbe_parent
)) do {} while (0); } while (0); tmp = (parent)->node.rbe_left
; } (tmp)->node.rbe_color = (parent)->node.rbe_color; (
parent)->node.rbe_color = 0; if ((tmp)->node.rbe_left) (
(tmp)->node.rbe_left)->node.rbe_color = 0; do { (tmp) =
(parent)->node.rbe_left; if (((parent)->node.rbe_left =
(tmp)->node.rbe_right)) { ((tmp)->node.rbe_right)->
node.rbe_parent = (parent); } do {} while (0); if (((tmp)->
node.rbe_parent = (parent)->node.rbe_parent)) { if ((parent
) == ((parent)->node.rbe_parent)->node.rbe_left) ((parent
)->node.rbe_parent)->node.rbe_left = (tmp); else ((parent
)->node.rbe_parent)->node.rbe_right = (tmp); } else (head
)->rbh_root = (tmp); (tmp)->node.rbe_right = (parent); (
parent)->node.rbe_parent = (tmp); do {} while (0); if (((tmp
)->node.rbe_parent)) do {} while (0); } while (0); elm = (
head)->rbh_root; break; } } } if (elm) (elm)->node.rbe_color
= 0; } struct magic_line * magic_named_tree_RB_REMOVE(struct
magic_named_tree *head, struct magic_line *elm) { struct magic_line
*child, *parent, *old = elm; int color; if ((elm)->node.rbe_left
== ((void *)0)) child = (elm)->node.rbe_right; else if ((
elm)->node.rbe_right == ((void *)0)) child = (elm)->node
.rbe_left; else { struct magic_line *left; elm = (elm)->node
.rbe_right; while ((left = (elm)->node.rbe_left)) elm = left
; child = (elm)->node.rbe_right; parent = (elm)->node.rbe_parent
; color = (elm)->node.rbe_color; if (child) (child)->node
.rbe_parent = parent; if (parent) { if ((parent)->node.rbe_left
== elm) (parent)->node.rbe_left = child; else (parent)->
node.rbe_right = child; do {} while (0); } else (head)->rbh_root
= child; if ((elm)->node.rbe_parent == old) parent = elm;
(elm)->node = (old)->node; if ((old)->node.rbe_parent
) { if (((old)->node.rbe_parent)->node.rbe_left == old)
((old)->node.rbe_parent)->node.rbe_left = elm; else ((
old)->node.rbe_parent)->node.rbe_right = elm; do {} while
(0); } else (head)->rbh_root = elm; ((old)->node.rbe_left
)->node.rbe_parent = elm; if ((old)->node.rbe_right) ((
old)->node.rbe_right)->node.rbe_parent = elm; if (parent
) { left = parent; do { do {} while (0); } while ((left = (left
)->node.rbe_parent)); } goto color; } parent = (elm)->node
.rbe_parent; color = (elm)->node.rbe_color; if (child) (child
)->node.rbe_parent = parent; if (parent) { if ((parent)->
node.rbe_left == elm) (parent)->node.rbe_left = child; else
(parent)->node.rbe_right = child; do {} while (0); } else
(head)->rbh_root = child; color: if (color == 0) magic_named_tree_RB_REMOVE_COLOR
(head, parent, child); return (old); } struct magic_line * magic_named_tree_RB_INSERT
(struct magic_named_tree *head, struct magic_line *elm) { struct
magic_line *tmp; struct magic_line *parent = ((void *)0); int
comp = 0; tmp = (head)->rbh_root; while (tmp) { parent = tmp
; comp = (magic_named_compare)(elm, parent); if (comp < 0)
tmp = (tmp)->node.rbe_left; else if (comp > 0) tmp = (
tmp)->node.rbe_right; else return (tmp); } do { (elm)->
node.rbe_parent = parent; (elm)->node.rbe_left = (elm)->
node.rbe_right = ((void *)0); (elm)->node.rbe_color = 1; }
while (0); if (parent != ((void *)0)) { if (comp < 0) (parent
)->node.rbe_left = elm; else (parent)->node.rbe_right =
elm; do {} while (0); } else (head)->rbh_root = elm; magic_named_tree_RB_INSERT_COLOR
(head, elm); return (((void *)0)); } struct magic_line * magic_named_tree_RB_FIND
(struct magic_named_tree *head, struct magic_line *elm) { struct
magic_line *tmp = (head)->rbh_root; int comp; while (tmp)
{ comp = magic_named_compare(elm, tmp); if (comp < 0) tmp
= (tmp)->node.rbe_left; else if (comp > 0) tmp = (tmp)
->node.rbe_right; else return (tmp); } return (((void *)0)
); } struct magic_line * magic_named_tree_RB_NFIND(struct magic_named_tree
*head, struct magic_line *elm) { struct magic_line *tmp = (head
)->rbh_root; struct magic_line *res = ((void *)0); int comp
; while (tmp) { comp = magic_named_compare(elm, tmp); if (comp
< 0) { res = tmp; tmp = (tmp)->node.rbe_left; } else if
(comp > 0) tmp = (tmp)->node.rbe_right; else return (tmp
); } return (res); } struct magic_line * magic_named_tree_RB_NEXT
(struct magic_line *elm) { if ((elm)->node.rbe_right) { elm
= (elm)->node.rbe_right; while ((elm)->node.rbe_left) elm
= (elm)->node.rbe_left; } else { if ((elm)->node.rbe_parent
&& (elm == ((elm)->node.rbe_parent)->node.rbe_left
)) elm = (elm)->node.rbe_parent; else { while ((elm)->node
.rbe_parent && (elm == ((elm)->node.rbe_parent)->
node.rbe_right)) elm = (elm)->node.rbe_parent; elm = (elm)
->node.rbe_parent; } } return (elm); } struct magic_line *
magic_named_tree_RB_PREV(struct magic_line *elm) { if ((elm)
->node.rbe_left) { elm = (elm)->node.rbe_left; while ((
elm)->node.rbe_right) elm = (elm)->node.rbe_right; } else
{ if ((elm)->node.rbe_parent && (elm == ((elm)->
node.rbe_parent)->node.rbe_right)) elm = (elm)->node.rbe_parent
; else { while ((elm)->node.rbe_parent && (elm == (
(elm)->node.rbe_parent)->node.rbe_left)) elm = (elm)->
node.rbe_parent; elm = (elm)->node.rbe_parent; } } return (
elm); } struct magic_line * magic_named_tree_RB_MINMAX(struct
magic_named_tree *head, int val) { struct magic_line *tmp = (
head)->rbh_root; struct magic_line *parent = ((void *)0); while
(tmp) { parent = tmp; if (val < 0) tmp = (tmp)->node.rbe_left
; else tmp = (tmp)->node.rbe_right; } return (parent); }
;
996
997static void
998magic_adjust_strength(struct magic *m, u_int at, struct magic_line *ml,
999 char *line)
1000{
1001 char *cp, *s;
1002 int64_t value;
1003
1004 cp = line + (sizeof "!:strength") - 1;
1005 while (isspace((u_char)*cp))
16
Loop condition is false. Execution continues on line 1007
1006 cp++;
1007 s = cp;
1008
1009 cp = strchr(s, '#');
1010 if (cp != NULL((void *)0))
17
Assuming 'cp' is equal to NULL
18
Taking false branch
1011 *cp = '\0';
1012 cp = s;
1013
1014 if (*s == '\0' || strchr("+-*/", *s) == NULL((void *)0)) {
19
Assuming the condition is false
20
Assuming the condition is false
21
Taking false branch
1015 magic_warnm(m, at, "invalid strength operator: %s", s);
1016 return;
1017 }
1018 ml->strength_operator = *cp++;
22
Access to field 'strength_operator' results in a dereference of a null pointer (loaded from variable 'ml')
1019
1020 while (isspace((u_char)*cp))
1021 cp++;
1022 cp = magic_strtoll(cp, &value);
1023 while (cp != NULL((void *)0) && isspace((u_char)*cp))
1024 cp++;
1025 if (cp == NULL((void *)0) || *cp != '\0' || value < 0 || value > 255) {
1026 magic_warnm(m, at, "invalid strength value: %s", s);
1027 return;
1028 }
1029 ml->strength_value = value;
1030}
1031
1032static void
1033magic_set_mimetype(struct magic *m, u_int at, struct magic_line *ml, char *line)
1034{
1035 char *mimetype, *cp;
1036
1037 mimetype = line + (sizeof "!:mime") - 1;
1038 while (isspace((u_char)*mimetype))
1039 mimetype++;
1040
1041 cp = strchr(mimetype, '#');
1042 if (cp != NULL((void *)0))
1043 *cp = '\0';
1044
1045 if (*mimetype != '\0') {
1046 cp = mimetype + strlen(mimetype) - 1;
1047 while (cp != mimetype && isspace((u_char)*cp))
1048 *cp-- = '\0';
1049 }
1050
1051 cp = mimetype;
1052 while (*cp != '\0') {
1053 if (!isalnum((u_char)*cp) && strchr("/-.+", *cp) == NULL((void *)0))
1054 break;
1055 cp++;
1056 }
1057 if (*mimetype == '\0' || *cp != '\0') {
1058 magic_warnm(m, at, "invalid MIME type: %s", mimetype);
1059 return;
1060 }
1061 if (ml == NULL((void *)0)) {
1062 magic_warnm(m, at, "stray MIME type: %s", mimetype);
1063 return;
1064 }
1065 ml->mimetype = xstrdup(mimetype);
1066}
1067
1068struct magic *
1069magic_load(FILE *f, const char *path, int warnings)
1070{
1071 struct magic *m;
1072 struct magic_line *ml = NULL((void *)0), *parent, *parent0;
1
'ml' initialized to a null pointer value
1073 char *line, *tmp;
1074 size_t size;
1075 ssize_t slen;
1076 u_int at, level, n, i;
1077
1078 m = xcalloc(1, sizeof *m);
1079 m->path = xstrdup(path);
1080 m->warnings = warnings;
1081 RB_INIT(&m->tree)do { (&m->tree)->rbh_root = ((void *)0); } while (0
)
;
2
Loop condition is false. Exiting loop
1082
1083 parent = NULL((void *)0);
1084 parent0 = NULL((void *)0);
1085 level = 0;
1086
1087 at = 0;
1088 tmp = NULL((void *)0);
1089 size = 0;
1090 while ((slen = getline(&tmp, &size, f)) != -1) {
3
Assuming the condition is true
4
Loop condition is true. Entering loop body
1091 line = tmp;
1092 if (line[slen - 1] == '\n')
5
Assuming the condition is false
6
Taking false branch
1093 line[slen - 1] = '\0';
1094
1095 at++;
1096
1097 while (isspace((u_char)*line))
7
Loop condition is false. Execution continues on line 1099
1098 line++;
1099 if (*line == '\0' || *line == '#')
8
Assuming the condition is false
9
Assuming the condition is false
10
Taking false branch
1100 continue;
1101
1102 if (strncmp (line, "!:mime", 6) == 0) {
11
Assuming the condition is false
12
Taking false branch
1103 magic_set_mimetype(m, at, ml, line);
1104 continue;
1105 }
1106 if (strncmp (line, "!:strength", 10) == 0) {
13
Taking true branch
1107 magic_adjust_strength(m, at, ml, line);
14
Passing null pointer value via 3rd parameter 'ml'
15
Calling 'magic_adjust_strength'
1108 continue;
1109 }
1110 if (strncmp (line, "!:", 2) == 0) {
1111 for (i = 0; i < 64 && line[i] != '\0'; i++) {
1112 if (isspace((u_char)line[i]))
1113 break;
1114 }
1115 magic_warnm(m, at, "%.*s not supported", i, line);
1116 continue;
1117 }
1118
1119 n = 0;
1120 for (; *line == '>'; line++)
1121 n++;
1122
1123 ml = xcalloc(1, sizeof *ml);
1124 ml->root = m;
1125 ml->line = at;
1126 ml->type = MAGIC_TYPE_NONE;
1127 TAILQ_INIT(&ml->children)do { (&ml->children)->tqh_first = ((void *)0); (&
ml->children)->tqh_last = &(&ml->children)->
tqh_first; } while (0)
;
1128 ml->text = 1;
1129
1130 /*
1131 * At this point n is the level we want, level is the current
1132 * level. parent0 is the last line at the same level and parent
1133 * is the last line at the previous level.
1134 */
1135 if (n == level + 1) {
1136 parent = parent0;
1137 } else if (n < level) {
1138 for (i = n; i < level && parent != NULL((void *)0); i++)
1139 parent = parent->parent;
1140 } else if (n != level) {
1141 magic_warn(ml, "level skipped (%u->%u)", level, n);
1142 free(ml);
1143 continue;
1144 }
1145 ml->parent = parent;
1146 level = n;
1147
1148 if (magic_parse_offset(ml, &line) != 0 ||
1149 magic_parse_type(ml, &line) != 0 ||
1150 magic_parse_value(ml, &line) != 0 ||
1151 magic_set_result(ml, line) != 0) {
1152 /*
1153 * An invalid line still needs to appear in the tree in
1154 * case it has any children.
1155 */
1156 ml->type = MAGIC_TYPE_NONE;
1157 }
1158
1159 ml->strength = magic_get_strength(ml);
1160 if (ml->parent == NULL((void *)0)) {
1161 if (ml->name != NULL((void *)0))
1162 RB_INSERT(magic_named_tree, &m->named, ml)magic_named_tree_RB_INSERT(&m->named, ml);
1163 else
1164 RB_INSERT(magic_tree, &m->tree, ml)magic_tree_RB_INSERT(&m->tree, ml);
1165 } else
1166 TAILQ_INSERT_TAIL(&ml->parent->children, ml, entry)do { (ml)->entry.tqe_next = ((void *)0); (ml)->entry.tqe_prev
= (&ml->parent->children)->tqh_last; *(&ml->
parent->children)->tqh_last = (ml); (&ml->parent
->children)->tqh_last = &(ml)->entry.tqe_next; }
while (0)
;
1167 parent0 = ml;
1168 }
1169 free(tmp);
1170 if (ferror(f)(!__isthreaded ? (((f)->_flags & 0x0040) != 0) : (ferror
)(f))
)
1171 err(1, "%s", path);
1172
1173 return (m);
1174}