00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037 #include "file.h"
00038 #include "magic.h"
00039 #include <string.h>
00040 #include <ctype.h>
00041 #include <stdlib.h>
00042 #include <time.h>
00043 #include <regex.h>
00044
00045
00046 #ifndef lint
00047 FILE_RCSID("@(#)$Id: softmagic.c,v 1.76 2005/10/17 19:04:36 christos Exp $")
00048 #endif
00049
00050 private int match(struct magic_set *ms, struct magic *magic, uint32_t nmagic,
00051 const unsigned char *s, size_t nbytes)
00052
00053 ;
00054 private int mget(struct magic_set *ms, union VALUETYPE *p, const unsigned char *s,
00055 struct magic *m, size_t nbytes, unsigned int cont_level)
00056
00057 ;
00058 private int mymcheck(struct magic_set *ms, union VALUETYPE *p, struct magic *m)
00059
00060 ;
00061 private int32_t mprint(struct magic_set *ms, union VALUETYPE *p, struct magic *m)
00062
00063 ;
00064 private void mdebug(uint32_t offset, const char *str, size_t len)
00065
00066 ;
00067 private int mcopy(struct magic_set *ms, union VALUETYPE *p, int type, int indir,
00068 const unsigned char *s, size_t offset, size_t nbytes)
00069 ;
00070 private int mconvert(struct magic_set *ms, union VALUETYPE *p, struct magic *m)
00071 ;
00072 private int check_mem(struct magic_set *ms, unsigned int level)
00073 ;
00074
00075
00076
00077
00078
00079
00080
00081 protected int
00082 file_softmagic(struct magic_set *ms, const unsigned char *buf, size_t nbytes)
00083 {
00084 struct mlist *ml;
00085 for (ml = ms->mlist->next; ml != ms->mlist; ml = ml->next)
00086 if (match(ms, ml->magic, ml->nmagic, buf, nbytes))
00087 return 1;
00088
00089 return 0;
00090 }
00091
00092
00093
00094
00095
00096
00097
00098
00099
00100
00101
00102
00103
00104
00105
00106
00107
00108
00109
00110
00111
00112
00113
00114
00115
00116
00117
00118
00119 private int
00120 match(struct magic_set *ms, struct magic *magic, uint32_t nmagic,
00121 const unsigned char *s, size_t nbytes)
00122 {
00123 uint32_t magindex = 0;
00124 unsigned int cont_level = 0;
00125 int need_separator = 0;
00126 union VALUETYPE p;
00127 int32_t oldoff = 0;
00128 int returnval = 0;
00129 int firstline = 1;
00130
00131 if (check_mem(ms, cont_level) == -1)
00132 return -1;
00133
00134 for (magindex = 0; magindex < nmagic; magindex++) {
00135
00136 int flush = !mget(ms, &p, s, &magic[magindex], nbytes,
00137 cont_level);
00138 if (flush) {
00139 if (magic[magindex].reln == '!') flush = 0;
00140 } else {
00141 switch (mymcheck(ms, &p, &magic[magindex])) {
00142 case -1:
00143 return -1;
00144 case 0:
00145 flush++;
00146 break;
00147 default:
00148 break;
00149 }
00150 }
00151 if (flush) {
00152
00153
00154
00155
00156 while (magindex < nmagic - 1 &&
00157 magic[magindex + 1].cont_level != 0)
00158 magindex++;
00159 continue;
00160 }
00161
00162 if (!firstline) {
00163
00164 if (file_printf(ms, "\n- ") == -1)
00165 return -1;
00166 }
00167
00168 if ((ms->c.off[cont_level] = mprint(ms, &p, &magic[magindex]))
00169 == -1)
00170 return -1;
00171
00172
00173
00174
00175 if (magic[magindex].desc[0])
00176 need_separator = 1;
00177
00178 if (check_mem(ms, ++cont_level) == -1)
00179 return -1;
00180
00181 while (magic[magindex+1].cont_level != 0 &&
00182 ++magindex < nmagic) {
00183 if (cont_level < magic[magindex].cont_level)
00184 continue;
00185 if (cont_level > magic[magindex].cont_level) {
00186
00187
00188
00189
00190 cont_level = magic[magindex].cont_level;
00191 }
00192 oldoff = magic[magindex].offset;
00193 if (magic[magindex].flag & OFFADD) {
00194 magic[magindex].offset +=
00195 ms->c.off[cont_level - 1];
00196 }
00197
00198 flush = !mget(ms, &p, s, &magic[magindex], nbytes,
00199 cont_level);
00200 if (flush && magic[magindex].reln != '!')
00201 goto done;
00202
00203 switch (flush ? 1 : mymcheck(ms, &p, &magic[magindex])) {
00204 case -1:
00205 return -1;
00206 case 0:
00207 break;
00208 default:
00209
00210
00211
00212
00213
00214
00215
00216
00217 if (need_separator
00218 && (magic[magindex].nospflag == 0)
00219 && (magic[magindex].desc[0] != '\0')) {
00220 if (file_printf(ms, " ") == -1)
00221 return -1;
00222 need_separator = 0;
00223 }
00224 if ((ms->c.off[cont_level] = mprint(ms, &p,
00225 &magic[magindex])) == -1)
00226 return -1;
00227 if (magic[magindex].desc[0])
00228 need_separator = 1;
00229
00230
00231
00232
00233
00234
00235 if (check_mem(ms, ++cont_level) == -1)
00236 return -1;
00237 }
00238 done:
00239 magic[magindex].offset = oldoff;
00240 }
00241 firstline = 0;
00242 returnval = 1;
00243 if ((ms->flags & MAGIC_CONTINUE) == 0) {
00244 return 1;
00245 }
00246 }
00247 return returnval;
00248 }
00249
00250 private int
00251 check_mem(struct magic_set *ms, unsigned int level)
00252 {
00253 size_t len;
00254
00255 if (level < ms->c.len)
00256 return 0;
00257
00258 len = (ms->c.len += 20) * sizeof(*ms->c.off);
00259 ms->c.off = (ms->c.off == NULL) ? malloc(len) : realloc(ms->c.off, len);
00260 if (ms->c.off != NULL)
00261 return 0;
00262 file_oomem(ms);
00263 return -1;
00264 }
00265
00266 private int32_t
00267 mprint(struct magic_set *ms, union VALUETYPE *p, struct magic *m)
00268 {
00269 uint32_t v;
00270 int32_t t=0 ;
00271
00272
00273 switch (m->type) {
00274 case FILE_BYTE:
00275 v = file_signextend(ms, m, (size_t)p->b);
00276 if (file_printf(ms, m->desc, (unsigned char) v) == -1)
00277 return -1;
00278 t = m->offset + sizeof(char);
00279 break;
00280
00281 case FILE_SHORT:
00282 case FILE_BESHORT:
00283 case FILE_LESHORT:
00284 v = file_signextend(ms, m, (size_t)p->h);
00285 if (file_printf(ms, m->desc, (unsigned short) v) == -1)
00286 return -1;
00287 t = m->offset + sizeof(short);
00288 break;
00289
00290 case FILE_LONG:
00291 case FILE_BELONG:
00292 case FILE_LELONG:
00293 v = file_signextend(ms, m, p->l);
00294 if (file_printf(ms, m->desc, (uint32_t) v) == -1)
00295 return -1;
00296 t = m->offset + sizeof(int32_t);
00297 break;
00298
00299 case FILE_STRING:
00300 case FILE_PSTRING:
00301 case FILE_BESTRING16:
00302 case FILE_LESTRING16:
00303 if (m->reln == '=' || m->reln == '!') {
00304 if (file_printf(ms, m->desc, m->value.s) == -1)
00305 return -1;
00306 t = m->offset + m->vallen;
00307 }
00308 else {
00309 if (*m->value.s == '\0') {
00310 char *cp = strchr(p->s,'\n');
00311 if (cp)
00312 *cp = '\0';
00313 }
00314 if (file_printf(ms, m->desc, p->s) == -1)
00315 return -1;
00316 t = m->offset + strlen(p->s);
00317 }
00318 break;
00319
00320 case FILE_DATE:
00321 case FILE_BEDATE:
00322 case FILE_LEDATE:
00323 if (file_printf(ms, m->desc, file_fmttime(p->l, 1)) == -1)
00324 return -1;
00325 t = m->offset + sizeof(time_t);
00326 break;
00327
00328 case FILE_LDATE:
00329 case FILE_BELDATE:
00330 case FILE_LELDATE:
00331 if (file_printf(ms, m->desc, file_fmttime(p->l, 0)) == -1)
00332 return -1;
00333 t = m->offset + sizeof(time_t);
00334 break;
00335 case FILE_REGEX:
00336 if (file_printf(ms, m->desc, p->s) == -1)
00337 return -1;
00338 t = m->offset + strlen(p->s);
00339 break;
00340 case FILE_SEARCH:
00341 if (file_printf(ms, m->desc, m->value.s) == -1)
00342 return -1;
00343 t = m->offset + m->vallen;
00344 break;
00345
00346 default:
00347 file_error(ms, 0, "invalid m->type (%d) in mprint()", m->type);
00348 return -1;
00349 }
00350 return(t);
00351 }
00352
00353
00354
00355
00356
00357
00358 private int
00359 mconvert(struct magic_set *ms, union VALUETYPE *p, struct magic *m)
00360 {
00361 switch (m->type) {
00362 case FILE_BYTE:
00363 if (m->mask)
00364 switch (m->mask_op & 0x7F) {
00365 case FILE_OPAND:
00366 p->b &= m->mask;
00367 break;
00368 case FILE_OPOR:
00369 p->b |= m->mask;
00370 break;
00371 case FILE_OPXOR:
00372 p->b ^= m->mask;
00373 break;
00374 case FILE_OPADD:
00375 p->b += m->mask;
00376 break;
00377 case FILE_OPMINUS:
00378 p->b -= m->mask;
00379 break;
00380 case FILE_OPMULTIPLY:
00381 p->b *= m->mask;
00382 break;
00383 case FILE_OPDIVIDE:
00384 p->b /= m->mask;
00385 break;
00386 case FILE_OPMODULO:
00387 p->b %= m->mask;
00388 break;
00389 }
00390 if (m->mask_op & FILE_OPINVERSE)
00391 p->b = ~p->b;
00392 return 1;
00393 case FILE_SHORT:
00394 if (m->mask)
00395 switch (m->mask_op & 0x7F) {
00396 case FILE_OPAND:
00397 p->h &= m->mask;
00398 break;
00399 case FILE_OPOR:
00400 p->h |= m->mask;
00401 break;
00402 case FILE_OPXOR:
00403 p->h ^= m->mask;
00404 break;
00405 case FILE_OPADD:
00406 p->h += m->mask;
00407 break;
00408 case FILE_OPMINUS:
00409 p->h -= m->mask;
00410 break;
00411 case FILE_OPMULTIPLY:
00412 p->h *= m->mask;
00413 break;
00414 case FILE_OPDIVIDE:
00415 p->h /= m->mask;
00416 break;
00417 case FILE_OPMODULO:
00418 p->h %= m->mask;
00419 break;
00420 }
00421 if (m->mask_op & FILE_OPINVERSE)
00422 p->h = ~p->h;
00423 return 1;
00424 case FILE_LONG:
00425 case FILE_DATE:
00426 case FILE_LDATE:
00427 if (m->mask)
00428 switch (m->mask_op & 0x7F) {
00429 case FILE_OPAND:
00430 p->l &= m->mask;
00431 break;
00432 case FILE_OPOR:
00433 p->l |= m->mask;
00434 break;
00435 case FILE_OPXOR:
00436 p->l ^= m->mask;
00437 break;
00438 case FILE_OPADD:
00439 p->l += m->mask;
00440 break;
00441 case FILE_OPMINUS:
00442 p->l -= m->mask;
00443 break;
00444 case FILE_OPMULTIPLY:
00445 p->l *= m->mask;
00446 break;
00447 case FILE_OPDIVIDE:
00448 p->l /= m->mask;
00449 break;
00450 case FILE_OPMODULO:
00451 p->l %= m->mask;
00452 break;
00453 }
00454 if (m->mask_op & FILE_OPINVERSE)
00455 p->l = ~p->l;
00456 return 1;
00457 case FILE_STRING:
00458 case FILE_BESTRING16:
00459 case FILE_LESTRING16:
00460 {
00461 size_t len;
00462
00463
00464 p->s[sizeof(p->s) - 1] = '\0';
00465 len = strlen(p->s);
00466 if (len-- && p->s[len] == '\n')
00467 p->s[len] = '\0';
00468 return 1;
00469 }
00470 case FILE_PSTRING:
00471 {
00472 char *ptr1 = p->s, *ptr2 = ptr1 + 1;
00473 size_t len = *p->s;
00474 if (len >= sizeof(p->s))
00475 len = sizeof(p->s) - 1;
00476 while (len--)
00477 *ptr1++ = *ptr2++;
00478 *ptr1 = '\0';
00479 len = strlen(p->s);
00480 if (len-- && p->s[len] == '\n')
00481 p->s[len] = '\0';
00482 return 1;
00483 }
00484 case FILE_BESHORT:
00485 p->h = (short)((p->hs[0]<<8)|(p->hs[1]));
00486 if (m->mask)
00487 switch (m->mask_op&0x7F) {
00488 case FILE_OPAND:
00489 p->h &= m->mask;
00490 break;
00491 case FILE_OPOR:
00492 p->h |= m->mask;
00493 break;
00494 case FILE_OPXOR:
00495 p->h ^= m->mask;
00496 break;
00497 case FILE_OPADD:
00498 p->h += m->mask;
00499 break;
00500 case FILE_OPMINUS:
00501 p->h -= m->mask;
00502 break;
00503 case FILE_OPMULTIPLY:
00504 p->h *= m->mask;
00505 break;
00506 case FILE_OPDIVIDE:
00507 p->h /= m->mask;
00508 break;
00509 case FILE_OPMODULO:
00510 p->h %= m->mask;
00511 break;
00512 }
00513 if (m->mask_op & FILE_OPINVERSE)
00514 p->h = ~p->h;
00515 return 1;
00516 case FILE_BELONG:
00517 case FILE_BEDATE:
00518 case FILE_BELDATE:
00519 p->l = (int32_t)
00520 ((p->hl[0]<<24)|(p->hl[1]<<16)|(p->hl[2]<<8)|(p->hl[3]));
00521 if (m->mask)
00522 switch (m->mask_op&0x7F) {
00523 case FILE_OPAND:
00524 p->l &= m->mask;
00525 break;
00526 case FILE_OPOR:
00527 p->l |= m->mask;
00528 break;
00529 case FILE_OPXOR:
00530 p->l ^= m->mask;
00531 break;
00532 case FILE_OPADD:
00533 p->l += m->mask;
00534 break;
00535 case FILE_OPMINUS:
00536 p->l -= m->mask;
00537 break;
00538 case FILE_OPMULTIPLY:
00539 p->l *= m->mask;
00540 break;
00541 case FILE_OPDIVIDE:
00542 p->l /= m->mask;
00543 break;
00544 case FILE_OPMODULO:
00545 p->l %= m->mask;
00546 break;
00547 }
00548 if (m->mask_op & FILE_OPINVERSE)
00549 p->l = ~p->l;
00550 return 1;
00551 case FILE_LESHORT:
00552 p->h = (short)((p->hs[1]<<8)|(p->hs[0]));
00553 if (m->mask)
00554 switch (m->mask_op&0x7F) {
00555 case FILE_OPAND:
00556 p->h &= m->mask;
00557 break;
00558 case FILE_OPOR:
00559 p->h |= m->mask;
00560 break;
00561 case FILE_OPXOR:
00562 p->h ^= m->mask;
00563 break;
00564 case FILE_OPADD:
00565 p->h += m->mask;
00566 break;
00567 case FILE_OPMINUS:
00568 p->h -= m->mask;
00569 break;
00570 case FILE_OPMULTIPLY:
00571 p->h *= m->mask;
00572 break;
00573 case FILE_OPDIVIDE:
00574 p->h /= m->mask;
00575 break;
00576 case FILE_OPMODULO:
00577 p->h %= m->mask;
00578 break;
00579 }
00580 if (m->mask_op & FILE_OPINVERSE)
00581 p->h = ~p->h;
00582 return 1;
00583 case FILE_LELONG:
00584 case FILE_LEDATE:
00585 case FILE_LELDATE:
00586 p->l = (int32_t)
00587 ((p->hl[3]<<24)|(p->hl[2]<<16)|(p->hl[1]<<8)|(p->hl[0]));
00588 if (m->mask)
00589 switch (m->mask_op&0x7F) {
00590 case FILE_OPAND:
00591 p->l &= m->mask;
00592 break;
00593 case FILE_OPOR:
00594 p->l |= m->mask;
00595 break;
00596 case FILE_OPXOR:
00597 p->l ^= m->mask;
00598 break;
00599 case FILE_OPADD:
00600 p->l += m->mask;
00601 break;
00602 case FILE_OPMINUS:
00603 p->l -= m->mask;
00604 break;
00605 case FILE_OPMULTIPLY:
00606 p->l *= m->mask;
00607 break;
00608 case FILE_OPDIVIDE:
00609 p->l /= m->mask;
00610 break;
00611 case FILE_OPMODULO:
00612 p->l %= m->mask;
00613 break;
00614 }
00615 if (m->mask_op & FILE_OPINVERSE)
00616 p->l = ~p->l;
00617 return 1;
00618 case FILE_REGEX:
00619 case FILE_SEARCH:
00620 return 1;
00621 default:
00622 file_error(ms, 0, "invalid type %d in mconvert()", m->type);
00623 return 0;
00624 }
00625 }
00626
00627
00628 private void
00629 mdebug(uint32_t offset, const char *str, size_t len)
00630 {
00631 (void) fprintf(stderr, "mget @%d: ", offset);
00632 file_showstr(stderr, str, len);
00633 (void) fputc('\n', stderr);
00634 (void) fputc('\n', stderr);
00635 }
00636
00637 private int
00638 mcopy(struct magic_set *ms, union VALUETYPE *p, int type, int indir,
00639 const unsigned char *s, size_t offset, size_t nbytes)
00640 {
00641 if (type == FILE_REGEX && indir == 0) {
00642
00643
00644
00645
00646 char *b, *c, *last = NULL;
00647 if ((p->search.buf = strdup((const char *)s)) == NULL) {
00648 file_oomem(ms);
00649 return -1;
00650 }
00651 for (b = p->search.buf; offset &&
00652 ((b = strchr(c = b, '\n')) != NULL || (b = strchr(c, '\r')) != NULL);
00653 offset--, b++) {
00654 last = b;
00655 if (b[0] == '\r' && b[1] == '\n') b++;
00656 }
00657 if (last != NULL)
00658 *last = '\0';
00659 p->search.buflen = last - p->search.buf;
00660 return 0;
00661 }
00662
00663 if (indir == 0 && (type == FILE_BESTRING16 || type == FILE_LESTRING16))
00664 {
00665 const unsigned char *src = s + offset;
00666 const unsigned char *esrc = s + nbytes;
00667 char *dst = p->s, *edst = &p->s[sizeof(p->s) - 1];
00668
00669 if (type == FILE_BESTRING16)
00670 src++;
00671
00672 for (;src < esrc; src++, dst++) {
00673 if (dst < edst)
00674 *dst = *src++;
00675 else
00676 break;
00677 if (*dst == '\0')
00678 *dst = ' ';
00679 }
00680 *edst = '\0';
00681 return 0;
00682 }
00683
00684 if (offset >= nbytes) {
00685 (void)memset(p, '\0', sizeof(*p));
00686 return 0;
00687 }
00688 if (nbytes - offset < sizeof(*p))
00689 nbytes = nbytes - offset;
00690 else
00691 nbytes = sizeof(*p);
00692
00693 (void)memcpy(p, s + offset, nbytes);
00694
00695
00696
00697
00698
00699 if (nbytes < sizeof(*p))
00700 (void)memset(((char *)(void *)p) + nbytes, '\0',
00701 sizeof(*p) - nbytes);
00702 return 0;
00703 }
00704
00705 private int
00706 mget(struct magic_set *ms, union VALUETYPE *p, const unsigned char *s,
00707 struct magic *m, size_t nbytes, unsigned int cont_level)
00708 {
00709 uint32_t offset = m->offset;
00710
00711 if (mcopy(ms, p, m->type, m->flag & INDIR, s, offset, nbytes) == -1)
00712 return -1;
00713
00714 if ((ms->flags & MAGIC_DEBUG) != 0) {
00715 mdebug(offset, (char *)(void *)p, sizeof(union VALUETYPE));
00716 file_mdump(m);
00717 }
00718
00719 if (m->flag & INDIR) {
00720 int off = m->in_offset;
00721 if (m->in_op & FILE_OPINDIRECT) {
00722 const union VALUETYPE *q =
00723 ((const void *)(s + offset + off));
00724 switch (m->in_type) {
00725 case FILE_BYTE:
00726 off = q->b;
00727 break;
00728 case FILE_SHORT:
00729 off = q->h;
00730 break;
00731 case FILE_BESHORT:
00732 off = (short)((q->hs[0]<<8)|(q->hs[1]));
00733 break;
00734 case FILE_LESHORT:
00735 off = (short)((q->hs[1]<<8)|(q->hs[0]));
00736 break;
00737 case FILE_LONG:
00738 off = q->l;
00739 break;
00740 case FILE_BELONG:
00741 off = (int32_t)((q->hl[0]<<24)|(q->hl[1]<<16)|
00742 (q->hl[2]<<8)|(q->hl[3]));
00743 break;
00744 case FILE_LELONG:
00745 off = (int32_t)((q->hl[3]<<24)|(q->hl[2]<<16)|
00746 (q->hl[1]<<8)|(q->hl[0]));
00747 break;
00748 }
00749 }
00750 switch (m->in_type) {
00751 case FILE_BYTE:
00752 if (nbytes < (offset + 1)) return 0;
00753 if (off) {
00754 switch (m->in_op & 0x3F) {
00755 case FILE_OPAND:
00756 offset = p->b & off;
00757 break;
00758 case FILE_OPOR:
00759 offset = p->b | off;
00760 break;
00761 case FILE_OPXOR:
00762 offset = p->b ^ off;
00763 break;
00764 case FILE_OPADD:
00765 offset = p->b + off;
00766 break;
00767 case FILE_OPMINUS:
00768 offset = p->b - off;
00769 break;
00770 case FILE_OPMULTIPLY:
00771 offset = p->b * off;
00772 break;
00773 case FILE_OPDIVIDE:
00774 offset = p->b / off;
00775 break;
00776 case FILE_OPMODULO:
00777 offset = p->b % off;
00778 break;
00779 }
00780 } else
00781 offset = p->b;
00782 if (m->in_op & FILE_OPINVERSE)
00783 offset = ~offset;
00784 break;
00785 case FILE_BESHORT:
00786 if (nbytes < (offset + 2))
00787 return 0;
00788 if (off) {
00789 switch (m->in_op & 0x7F) {
00790 case FILE_OPAND:
00791 offset = (short)((p->hs[0]<<8)|
00792 (p->hs[1])) &
00793 off;
00794 break;
00795 case FILE_OPOR:
00796 offset = (short)((p->hs[0]<<8)|
00797 (p->hs[1])) |
00798 off;
00799 break;
00800 case FILE_OPXOR:
00801 offset = (short)((p->hs[0]<<8)|
00802 (p->hs[1])) ^
00803 off;
00804 break;
00805 case FILE_OPADD:
00806 offset = (short)((p->hs[0]<<8)|
00807 (p->hs[1])) +
00808 off;
00809 break;
00810 case FILE_OPMINUS:
00811 offset = (short)((p->hs[0]<<8)|
00812 (p->hs[1])) -
00813 off;
00814 break;
00815 case FILE_OPMULTIPLY:
00816 offset = (short)((p->hs[0]<<8)|
00817 (p->hs[1])) *
00818 off;
00819 break;
00820 case FILE_OPDIVIDE:
00821 offset = (short)((p->hs[0]<<8)|
00822 (p->hs[1])) /
00823 off;
00824 break;
00825 case FILE_OPMODULO:
00826 offset = (short)((p->hs[0]<<8)|
00827 (p->hs[1])) %
00828 off;
00829 break;
00830 }
00831 } else
00832 offset = (short)((p->hs[0]<<8)|
00833 (p->hs[1]));
00834 if (m->in_op & FILE_OPINVERSE)
00835 offset = ~offset;
00836 break;
00837 case FILE_LESHORT:
00838 if (nbytes < (offset + 2))
00839 return 0;
00840 if (off) {
00841 switch (m->in_op & 0x7F) {
00842 case FILE_OPAND:
00843 offset = (short)((p->hs[1]<<8)|
00844 (p->hs[0])) &
00845 off;
00846 break;
00847 case FILE_OPOR:
00848 offset = (short)((p->hs[1]<<8)|
00849 (p->hs[0])) |
00850 off;
00851 break;
00852 case FILE_OPXOR:
00853 offset = (short)((p->hs[1]<<8)|
00854 (p->hs[0])) ^
00855 off;
00856 break;
00857 case FILE_OPADD:
00858 offset = (short)((p->hs[1]<<8)|
00859 (p->hs[0])) +
00860 off;
00861 break;
00862 case FILE_OPMINUS:
00863 offset = (short)((p->hs[1]<<8)|
00864 (p->hs[0])) -
00865 off;
00866 break;
00867 case FILE_OPMULTIPLY:
00868 offset = (short)((p->hs[1]<<8)|
00869 (p->hs[0])) *
00870 off;
00871 break;
00872 case FILE_OPDIVIDE:
00873 offset = (short)((p->hs[1]<<8)|
00874 (p->hs[0])) /
00875 off;
00876 break;
00877 case FILE_OPMODULO:
00878 offset = (short)((p->hs[1]<<8)|
00879 (p->hs[0])) %
00880 off;
00881 break;
00882 }
00883 } else
00884 offset = (short)((p->hs[1]<<8)|
00885 (p->hs[0]));
00886 if (m->in_op & FILE_OPINVERSE)
00887 offset = ~offset;
00888 break;
00889 case FILE_SHORT:
00890 if (nbytes < (offset + 2))
00891 return 0;
00892 if (off) {
00893 switch (m->in_op & 0x7F) {
00894 case FILE_OPAND:
00895 offset = p->h & off;
00896 break;
00897 case FILE_OPOR:
00898 offset = p->h | off;
00899 break;
00900 case FILE_OPXOR:
00901 offset = p->h ^ off;
00902 break;
00903 case FILE_OPADD:
00904 offset = p->h + off;
00905 break;
00906 case FILE_OPMINUS:
00907 offset = p->h - off;
00908 break;
00909 case FILE_OPMULTIPLY:
00910 offset = p->h * off;
00911 break;
00912 case FILE_OPDIVIDE:
00913 offset = p->h / off;
00914 break;
00915 case FILE_OPMODULO:
00916 offset = p->h % off;
00917 break;
00918 }
00919 }
00920 else
00921 offset = p->h;
00922 if (m->in_op & FILE_OPINVERSE)
00923 offset = ~offset;
00924 break;
00925 case FILE_BELONG:
00926 if (nbytes < (offset + 4))
00927 return 0;
00928 if (off) {
00929 switch (m->in_op & 0x7F) {
00930 case FILE_OPAND:
00931 offset = (int32_t)((p->hl[0]<<24)|
00932 (p->hl[1]<<16)|
00933 (p->hl[2]<<8)|
00934 (p->hl[3])) &
00935 off;
00936 break;
00937 case FILE_OPOR:
00938 offset = (int32_t)((p->hl[0]<<24)|
00939 (p->hl[1]<<16)|
00940 (p->hl[2]<<8)|
00941 (p->hl[3])) |
00942 off;
00943 break;
00944 case FILE_OPXOR:
00945 offset = (int32_t)((p->hl[0]<<24)|
00946 (p->hl[1]<<16)|
00947 (p->hl[2]<<8)|
00948 (p->hl[3])) ^
00949 off;
00950 break;
00951 case FILE_OPADD:
00952 offset = (int32_t)((p->hl[0]<<24)|
00953 (p->hl[1]<<16)|
00954 (p->hl[2]<<8)|
00955 (p->hl[3])) +
00956 off;
00957 break;
00958 case FILE_OPMINUS:
00959 offset = (int32_t)((p->hl[0]<<24)|
00960 (p->hl[1]<<16)|
00961 (p->hl[2]<<8)|
00962 (p->hl[3])) -
00963 off;
00964 break;
00965 case FILE_OPMULTIPLY:
00966 offset = (int32_t)((p->hl[0]<<24)|
00967 (p->hl[1]<<16)|
00968 (p->hl[2]<<8)|
00969 (p->hl[3])) *
00970 off;
00971 break;
00972 case FILE_OPDIVIDE:
00973 offset = (int32_t)((p->hl[0]<<24)|
00974 (p->hl[1]<<16)|
00975 (p->hl[2]<<8)|
00976 (p->hl[3])) /
00977 off;
00978 break;
00979 case FILE_OPMODULO:
00980 offset = (int32_t)((p->hl[0]<<24)|
00981 (p->hl[1]<<16)|
00982 (p->hl[2]<<8)|
00983 (p->hl[3])) %
00984 off;
00985 break;
00986 }
00987 } else
00988 offset = (int32_t)((p->hl[0]<<24)|
00989 (p->hl[1]<<16)|
00990 (p->hl[2]<<8)|
00991 (p->hl[3]));
00992 if (m->in_op & FILE_OPINVERSE)
00993 offset = ~offset;
00994 break;
00995 case FILE_LELONG:
00996 if (nbytes < (offset + 4))
00997 return 0;
00998 if (off) {
00999 switch (m->in_op & 0x7F) {
01000 case FILE_OPAND:
01001 offset = (int32_t)((p->hl[3]<<24)|
01002 (p->hl[2]<<16)|
01003 (p->hl[1]<<8)|
01004 (p->hl[0])) &
01005 off;
01006 break;
01007 case FILE_OPOR:
01008 offset = (int32_t)((p->hl[3]<<24)|
01009 (p->hl[2]<<16)|
01010 (p->hl[1]<<8)|
01011 (p->hl[0])) |
01012 off;
01013 break;
01014 case FILE_OPXOR:
01015 offset = (int32_t)((p->hl[3]<<24)|
01016 (p->hl[2]<<16)|
01017 (p->hl[1]<<8)|
01018 (p->hl[0])) ^
01019 off;
01020 break;
01021 case FILE_OPADD:
01022 offset = (int32_t)((p->hl[3]<<24)|
01023 (p->hl[2]<<16)|
01024 (p->hl[1]<<8)|
01025 (p->hl[0])) +
01026 off;
01027 break;
01028 case FILE_OPMINUS:
01029 offset = (int32_t)((p->hl[3]<<24)|
01030 (p->hl[2]<<16)|
01031 (p->hl[1]<<8)|
01032 (p->hl[0])) -
01033 off;
01034 break;
01035 case FILE_OPMULTIPLY:
01036 offset = (int32_t)((p->hl[3]<<24)|
01037 (p->hl[2]<<16)|
01038 (p->hl[1]<<8)|
01039 (p->hl[0])) *
01040 off;
01041 break;
01042 case FILE_OPDIVIDE:
01043 offset = (int32_t)((p->hl[3]<<24)|
01044 (p->hl[2]<<16)|
01045 (p->hl[1]<<8)|
01046 (p->hl[0])) /
01047 off;
01048 break;
01049 case FILE_OPMODULO:
01050 offset = (int32_t)((p->hl[3]<<24)|
01051 (p->hl[2]<<16)|
01052 (p->hl[1]<<8)|
01053 (p->hl[0])) %
01054 off;
01055 break;
01056 }
01057 } else
01058 offset = (int32_t)((p->hl[3]<<24)|
01059 (p->hl[2]<<16)|
01060 (p->hl[1]<<8)|
01061 (p->hl[0]));
01062 if (m->in_op & FILE_OPINVERSE)
01063 offset = ~offset;
01064 break;
01065 case FILE_LONG:
01066 if (nbytes < (offset + 4))
01067 return 0;
01068 if (off) {
01069 switch (m->in_op & 0x7F) {
01070 case FILE_OPAND:
01071 offset = p->l & off;
01072 break;
01073 case FILE_OPOR:
01074 offset = p->l | off;
01075 break;
01076 case FILE_OPXOR:
01077 offset = p->l ^ off;
01078 break;
01079 case FILE_OPADD:
01080 offset = p->l + off;
01081 break;
01082 case FILE_OPMINUS:
01083 offset = p->l - off;
01084 break;
01085 case FILE_OPMULTIPLY:
01086 offset = p->l * off;
01087 break;
01088 case FILE_OPDIVIDE:
01089 offset = p->l / off;
01090 break;
01091 case FILE_OPMODULO:
01092 offset = p->l % off;
01093 break;
01094
01095
01096
01097
01098
01099
01100
01101 }
01102 } else
01103 offset = p->l;
01104 if (m->in_op & FILE_OPINVERSE)
01105 offset = ~offset;
01106 break;
01107 }
01108
01109 if (m->flag & INDIROFFADD) offset += ms->c.off[cont_level-1];
01110 if (mcopy(ms, p, m->type, 0, s, offset, nbytes) == -1)
01111 return -1;
01112 m->offset = offset;
01113
01114 if ((ms->flags & MAGIC_DEBUG) != 0) {
01115 mdebug(offset, (char *)(void *)p,
01116 sizeof(union VALUETYPE));
01117 file_mdump(m);
01118 }
01119 }
01120
01121
01122 switch (m->type) {
01123 case FILE_BYTE:
01124 if (nbytes < (offset + 1))
01125 return 0;
01126 break;
01127
01128 case FILE_SHORT:
01129 case FILE_BESHORT:
01130 case FILE_LESHORT:
01131 if (nbytes < (offset + 2))
01132 return 0;
01133 break;
01134
01135 case FILE_LONG:
01136 case FILE_BELONG:
01137 case FILE_LELONG:
01138 case FILE_DATE:
01139 case FILE_BEDATE:
01140 case FILE_LEDATE:
01141 case FILE_LDATE:
01142 case FILE_BELDATE:
01143 case FILE_LELDATE:
01144 if (nbytes < (offset + 4))
01145 return 0;
01146 break;
01147
01148 case FILE_STRING:
01149 case FILE_PSTRING:
01150 case FILE_SEARCH:
01151 if (nbytes < (offset + m->vallen))
01152 return 0;
01153 break;
01154 default: break;
01155 }
01156
01157 if (m->type == FILE_SEARCH) {
01158 size_t mlen = m->mask + m->vallen;
01159 size_t flen = nbytes - offset;
01160 if (flen < mlen)
01161 mlen = flen;
01162 p->search.buflen = mlen;
01163 p->search.buf = malloc(mlen + 1);
01164 if (p->search.buf == NULL) {
01165 file_error(ms, errno, "Cannot allocate search buffer");
01166 return 0;
01167 }
01168 (void)memcpy(p->search.buf, s + offset, mlen);
01169 p->search.buf[mlen] = '\0';
01170 }
01171 if (!mconvert(ms, p, m))
01172 return 0;
01173 return 1;
01174 }
01175
01176 private int
01177 mymcheck(struct magic_set *ms, union VALUETYPE *p, struct magic *m)
01178 {
01179 uint32_t l = m->value.l;
01180 uint32_t v;
01181 int matched;
01182
01183 if ( (m->value.s[0] == 'x') && (m->value.s[1] == '\0') ) {
01184 return 1;
01185 }
01186
01187
01188 switch (m->type) {
01189 case FILE_BYTE:
01190 v = p->b;
01191 break;
01192
01193 case FILE_SHORT:
01194 case FILE_BESHORT:
01195 case FILE_LESHORT:
01196 v = p->h;
01197 break;
01198
01199 case FILE_LONG:
01200 case FILE_BELONG:
01201 case FILE_LELONG:
01202 case FILE_DATE:
01203 case FILE_BEDATE:
01204 case FILE_LEDATE:
01205 case FILE_LDATE:
01206 case FILE_BELDATE:
01207 case FILE_LELDATE:
01208 v = p->l;
01209 break;
01210
01211 case FILE_STRING:
01212 case FILE_BESTRING16:
01213 case FILE_LESTRING16:
01214 case FILE_PSTRING:
01215 {
01216
01217
01218
01219
01220
01221
01222 unsigned char *a = (unsigned char*)m->value.s;
01223 unsigned char *b = (unsigned char*)p->s;
01224 int len = m->vallen;
01225 l = 0;
01226 v = 0;
01227 if (0L == m->mask) {
01228 while (--len >= 0)
01229 if ((v = *b++ - *a++) != '\0')
01230 break;
01231 } else {
01232 while (--len >= 0) {
01233 if ((m->mask & STRING_IGNORE_LOWERCASE) &&
01234 islower(*a)) {
01235 if ((v = tolower(*b++) - *a++) != '\0')
01236 break;
01237 } else if ((m->mask & STRING_COMPACT_BLANK) &&
01238 isspace(*a)) {
01239 a++;
01240 if (isspace(*b++)) {
01241 while (isspace(*b))
01242 b++;
01243 } else {
01244 v = 1;
01245 break;
01246 }
01247 } else if (isspace(*a) &&
01248 (m->mask & STRING_COMPACT_OPTIONAL_BLANK)) {
01249 a++;
01250 while (isspace(*b))
01251 b++;
01252 } else {
01253 if ((v = *b++ - *a++) != '\0')
01254 break;
01255 }
01256 }
01257 }
01258 break;
01259 }
01260 case FILE_REGEX:
01261 {
01262 int rc;
01263 regex_t rx;
01264 char errmsg[512];
01265
01266 if (p->search.buf == NULL)
01267 return 0;
01268
01269 rc = regcomp(&rx, m->value.s,
01270 REG_EXTENDED|REG_NOSUB|REG_NEWLINE|
01271 ((m->mask & STRING_IGNORE_LOWERCASE) ? REG_ICASE : 0));
01272 if (rc) {
01273 free(p->search.buf);
01274 p->search.buf = NULL;
01275 (void) regerror(rc, &rx, errmsg, sizeof(errmsg));
01276 file_error(ms, 0, "regex error %d, (%s)", rc, errmsg);
01277 return -1;
01278 } else {
01279 rc = regexec(&rx, p->search.buf, 0, 0, 0);
01280 regfree(&rx);
01281 free(p->search.buf);
01282 p->search.buf = NULL;
01283 return !rc;
01284 }
01285 }
01286 case FILE_SEARCH:
01287 {
01288
01289
01290
01291 unsigned char *a = (unsigned char*)m->value.s;
01292 unsigned char *b = (unsigned char*)p->search.buf;
01293 size_t len, slen = m->vallen;
01294 size_t range = 0;
01295 if (slen > sizeof(m->value.s))
01296 slen = sizeof(m->value.s);
01297 l = 0;
01298 v = 0;
01299 if (b == NULL)
01300 return 0;
01301 len = slen;
01302 while (++range <= m->mask) {
01303 while (len-- > 0 && (v = *b++ - *a++) == 0)
01304 continue;
01305 if (!v) {
01306 m->offset += range - 1;
01307 break;
01308 }
01309 if (range + slen >= p->search.buflen)
01310 break;
01311 len = slen;
01312 a = (unsigned char*)m->value.s;
01313 b = (unsigned char*)p->search.buf + range;
01314 }
01315 free(p->search.buf);
01316 p->search.buf = NULL;
01317 break;
01318 }
01319 default:
01320 file_error(ms, 0, "invalid type %d in mcheck()", m->type);
01321 return -1;
01322 }
01323
01324 if (m->type != FILE_STRING && m->type != FILE_PSTRING)
01325 v = file_signextend(ms, m, v);
01326
01327 switch (m->reln) {
01328 case 'x':
01329 if ((ms->flags & MAGIC_DEBUG) != 0)
01330 (void) fprintf(stderr, "%u == *any* = 1\n", v);
01331 matched = 1;
01332 break;
01333
01334 case '!':
01335 matched = v != l;
01336 if ((ms->flags & MAGIC_DEBUG) != 0)
01337 (void) fprintf(stderr, "%u != %u = %d\n",
01338 v, l, matched);
01339 break;
01340
01341 case '=':
01342 matched = v == l;
01343 if ((ms->flags & MAGIC_DEBUG) != 0)
01344 (void) fprintf(stderr, "%u == %u = %d\n",
01345 v, l, matched);
01346 break;
01347
01348 case '>':
01349 if (m->flag & UNSIGNED) {
01350 matched = v > l;
01351 if ((ms->flags & MAGIC_DEBUG) != 0)
01352 (void) fprintf(stderr, "%u > %u = %d\n",
01353 v, l, matched);
01354 }
01355 else {
01356 matched = (int32_t) v > (int32_t) l;
01357 if ((ms->flags & MAGIC_DEBUG) != 0)
01358 (void) fprintf(stderr, "%d > %d = %d\n",
01359 v, l, matched);
01360 }
01361 break;
01362
01363 case '<':
01364 if (m->flag & UNSIGNED) {
01365 matched = v < l;
01366 if ((ms->flags & MAGIC_DEBUG) != 0)
01367 (void) fprintf(stderr, "%u < %u = %d\n",
01368 v, l, matched);
01369 }
01370 else {
01371 matched = (int32_t) v < (int32_t) l;
01372 if ((ms->flags & MAGIC_DEBUG) != 0)
01373 (void) fprintf(stderr, "%d < %d = %d\n",
01374 v, l, matched);
01375 }
01376 break;
01377
01378 case '&':
01379 matched = (v & l) == l;
01380 if ((ms->flags & MAGIC_DEBUG) != 0)
01381 (void) fprintf(stderr, "((%x & %x) == %x) = %d\n",
01382 v, l, l, matched);
01383 break;
01384
01385 case '^':
01386 matched = (v & l) != l;
01387 if ((ms->flags & MAGIC_DEBUG) != 0)
01388 (void) fprintf(stderr, "((%x & %x) != %x) = %d\n",
01389 v, l, l, matched);
01390 break;
01391
01392 default:
01393 matched = 0;
01394 file_error(ms, 0, "cannot happen: invalid relation `%c'",
01395 m->reln);
01396 return -1;
01397 }
01398
01399 return matched;
01400 }
01401
01402
01403
01404
01405