softmagic.c 31 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381
  1. /*
  2. * Copyright (c) Ian F. Darwin 1986-1995.
  3. * Software written by Ian F. Darwin and others;
  4. * maintained 1995-present by Christos Zoulas and others.
  5. *
  6. * Redistribution and use in source and binary forms, with or without
  7. * modification, are permitted provided that the following conditions
  8. * are met:
  9. * 1. Redistributions of source code must retain the above copyright
  10. * notice immediately at the beginning of the file, without modification,
  11. * this list of conditions, and the following disclaimer.
  12. * 2. Redistributions in binary form must reproduce the above copyright
  13. * notice, this list of conditions and the following disclaimer in the
  14. * documentation and/or other materials provided with the distribution.
  15. *
  16. * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
  17. * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  18. * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  19. * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
  20. * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  21. * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  22. * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  23. * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  24. * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  25. * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  26. * SUCH DAMAGE.
  27. */
  28. /*
  29. * softmagic - interpret variable magic from MAGIC
  30. */
  31. #include "file.h"
  32. #include "magic.h"
  33. #include <string.h>
  34. #include <ctype.h>
  35. #include <stdlib.h>
  36. #include <time.h>
  37. #include <regex.h>
  38. #ifndef lint
  39. FILE_RCSID("@(#)$Id: softmagic.c,v 1.74 2005/07/29 17:57:20 christos Exp $")
  40. #endif /* lint */
  41. private int match(struct magic_set *, struct magic *, uint32_t,
  42. const unsigned char *, size_t);
  43. private int mget(struct magic_set *, union VALUETYPE *, const unsigned char *,
  44. struct magic *, size_t, int);
  45. private int mcheck(struct magic_set *, union VALUETYPE *, struct magic *);
  46. private int32_t mprint(struct magic_set *, union VALUETYPE *, struct magic *);
  47. private void mdebug(uint32_t, const char *, size_t);
  48. private int mcopy(struct magic_set *, union VALUETYPE *, int, int,
  49. const unsigned char *, size_t, size_t);
  50. private int mconvert(struct magic_set *, union VALUETYPE *, struct magic *);
  51. private int check_mem(struct magic_set *, unsigned int);
  52. /*
  53. * softmagic - lookup one file in database
  54. * (already read from MAGIC by apprentice.c).
  55. * Passed the name and FILE * of one file to be typed.
  56. */
  57. /*ARGSUSED1*/ /* nbytes passed for regularity, maybe need later */
  58. protected int
  59. file_softmagic(struct magic_set *ms, const unsigned char *buf, size_t nbytes)
  60. {
  61. struct mlist *ml;
  62. for (ml = ms->mlist->next; ml != ms->mlist; ml = ml->next)
  63. if (match(ms, ml->magic, ml->nmagic, buf, nbytes))
  64. return 1;
  65. return 0;
  66. }
  67. /*
  68. * Go through the whole list, stopping if you find a match. Process all
  69. * the continuations of that match before returning.
  70. *
  71. * We support multi-level continuations:
  72. *
  73. * At any time when processing a successful top-level match, there is a
  74. * current continuation level; it represents the level of the last
  75. * successfully matched continuation.
  76. *
  77. * Continuations above that level are skipped as, if we see one, it
  78. * means that the continuation that controls them - i.e, the
  79. * lower-level continuation preceding them - failed to match.
  80. *
  81. * Continuations below that level are processed as, if we see one,
  82. * it means we've finished processing or skipping higher-level
  83. * continuations under the control of a successful or unsuccessful
  84. * lower-level continuation, and are now seeing the next lower-level
  85. * continuation and should process it. The current continuation
  86. * level reverts to the level of the one we're seeing.
  87. *
  88. * Continuations at the current level are processed as, if we see
  89. * one, there's no lower-level continuation that may have failed.
  90. *
  91. * If a continuation matches, we bump the current continuation level
  92. * so that higher-level continuations are processed.
  93. */
  94. private int
  95. match(struct magic_set *ms, struct magic *magic, uint32_t nmagic,
  96. const unsigned char *s, size_t nbytes)
  97. {
  98. uint32_t magindex = 0;
  99. unsigned int cont_level = 0;
  100. int need_separator = 0;
  101. union VALUETYPE p;
  102. int32_t oldoff = 0;
  103. int returnval = 0; /* if a match is found it is set to 1*/
  104. int firstline = 1; /* a flag to print X\n X\n- X */
  105. if (check_mem(ms, cont_level) == -1)
  106. return -1;
  107. for (magindex = 0; magindex < nmagic; magindex++) {
  108. /* if main entry matches, print it... */
  109. int flush = !mget(ms, &p, s, &magic[magindex], nbytes,
  110. cont_level);
  111. if (flush) {
  112. if (magic[magindex].reln == '!') flush = 0;
  113. } else {
  114. switch (mcheck(ms, &p, &magic[magindex])) {
  115. case -1:
  116. return -1;
  117. case 0:
  118. flush++;
  119. break;
  120. default:
  121. break;
  122. }
  123. }
  124. if (flush) {
  125. /*
  126. * main entry didn't match,
  127. * flush its continuations
  128. */
  129. while (magindex < nmagic - 1 &&
  130. magic[magindex + 1].cont_level != 0)
  131. magindex++;
  132. continue;
  133. }
  134. if (!firstline) { /* we found another match */
  135. /* put a newline and '-' to do some simple formatting*/
  136. if (file_printf(ms, "\n- ") == -1)
  137. return -1;
  138. }
  139. if ((ms->c.off[cont_level] = mprint(ms, &p, &magic[magindex]))
  140. == -1)
  141. return -1;
  142. /*
  143. * If we printed something, we'll need to print
  144. * a blank before we print something else.
  145. */
  146. if (magic[magindex].desc[0])
  147. need_separator = 1;
  148. /* and any continuations that match */
  149. if (check_mem(ms, ++cont_level) == -1)
  150. return -1;
  151. while (magic[magindex+1].cont_level != 0 &&
  152. ++magindex < nmagic) {
  153. if (cont_level < magic[magindex].cont_level)
  154. continue;
  155. if (cont_level > magic[magindex].cont_level) {
  156. /*
  157. * We're at the end of the level
  158. * "cont_level" continuations.
  159. */
  160. cont_level = magic[magindex].cont_level;
  161. }
  162. oldoff = magic[magindex].offset;
  163. if (magic[magindex].flag & OFFADD) {
  164. magic[magindex].offset +=
  165. ms->c.off[cont_level - 1];
  166. }
  167. flush = !mget(ms, &p, s, &magic[magindex], nbytes,
  168. cont_level);
  169. if (flush && magic[magindex].reln != '!')
  170. goto done;
  171. switch (flush ? 1 : mcheck(ms, &p, &magic[magindex])) {
  172. case -1:
  173. return -1;
  174. case 0:
  175. break;
  176. default:
  177. /*
  178. * This continuation matched.
  179. * Print its message, with
  180. * a blank before it if
  181. * the previous item printed
  182. * and this item isn't empty.
  183. */
  184. /* space if previous printed */
  185. if (need_separator
  186. && (magic[magindex].nospflag == 0)
  187. && (magic[magindex].desc[0] != '\0')) {
  188. if (file_printf(ms, " ") == -1)
  189. return -1;
  190. need_separator = 0;
  191. }
  192. if ((ms->c.off[cont_level] = mprint(ms, &p,
  193. &magic[magindex])) == -1)
  194. return -1;
  195. if (magic[magindex].desc[0])
  196. need_separator = 1;
  197. /*
  198. * If we see any continuations
  199. * at a higher level,
  200. * process them.
  201. */
  202. if (check_mem(ms, ++cont_level) == -1)
  203. return -1;
  204. }
  205. done:
  206. magic[magindex].offset = oldoff;
  207. }
  208. firstline = 0;
  209. returnval = 1;
  210. if ((ms->flags & MAGIC_CONTINUE) == 0) {
  211. return 1; /* don't keep searching */
  212. }
  213. }
  214. return returnval; /* This is hit if -k is set or there is no match */
  215. }
  216. private int
  217. check_mem(struct magic_set *ms, unsigned int level)
  218. {
  219. size_t len;
  220. if (level < ms->c.len)
  221. return 0;
  222. len = (ms->c.len += 20) * sizeof(*ms->c.off);
  223. ms->c.off = (ms->c.off == NULL) ? malloc(len) : realloc(ms->c.off, len);
  224. if (ms->c.off != NULL)
  225. return 0;
  226. file_oomem(ms);
  227. return -1;
  228. }
  229. private int32_t
  230. mprint(struct magic_set *ms, union VALUETYPE *p, struct magic *m)
  231. {
  232. uint32_t v;
  233. int32_t t=0 ;
  234. switch (m->type) {
  235. case FILE_BYTE:
  236. v = file_signextend(ms, m, (size_t)p->b);
  237. if (file_printf(ms, m->desc, (unsigned char) v) == -1)
  238. return -1;
  239. t = m->offset + sizeof(char);
  240. break;
  241. case FILE_SHORT:
  242. case FILE_BESHORT:
  243. case FILE_LESHORT:
  244. v = file_signextend(ms, m, (size_t)p->h);
  245. if (file_printf(ms, m->desc, (unsigned short) v) == -1)
  246. return -1;
  247. t = m->offset + sizeof(short);
  248. break;
  249. case FILE_LONG:
  250. case FILE_BELONG:
  251. case FILE_LELONG:
  252. v = file_signextend(ms, m, p->l);
  253. if (file_printf(ms, m->desc, (uint32_t) v) == -1)
  254. return -1;
  255. t = m->offset + sizeof(int32_t);
  256. break;
  257. case FILE_STRING:
  258. case FILE_PSTRING:
  259. case FILE_BESTRING16:
  260. case FILE_LESTRING16:
  261. if (m->reln == '=' || m->reln == '!') {
  262. if (file_printf(ms, m->desc, m->value.s) == -1)
  263. return -1;
  264. t = m->offset + m->vallen;
  265. }
  266. else {
  267. if (*m->value.s == '\0') {
  268. char *cp = strchr(p->s,'\n');
  269. if (cp)
  270. *cp = '\0';
  271. }
  272. if (file_printf(ms, m->desc, p->s) == -1)
  273. return -1;
  274. t = m->offset + strlen(p->s);
  275. }
  276. break;
  277. case FILE_DATE:
  278. case FILE_BEDATE:
  279. case FILE_LEDATE:
  280. if (file_printf(ms, m->desc, file_fmttime(p->l, 1)) == -1)
  281. return -1;
  282. t = m->offset + sizeof(time_t);
  283. break;
  284. case FILE_LDATE:
  285. case FILE_BELDATE:
  286. case FILE_LELDATE:
  287. if (file_printf(ms, m->desc, file_fmttime(p->l, 0)) == -1)
  288. return -1;
  289. t = m->offset + sizeof(time_t);
  290. break;
  291. case FILE_REGEX:
  292. if (file_printf(ms, m->desc, p->s) == -1)
  293. return -1;
  294. t = m->offset + strlen(p->s);
  295. break;
  296. case FILE_SEARCH:
  297. if (file_printf(ms, m->desc, m->value.s) == -1)
  298. return -1;
  299. t = m->offset + m->vallen;
  300. break;
  301. default:
  302. file_error(ms, 0, "invalid m->type (%d) in mprint()", m->type);
  303. return -1;
  304. }
  305. return(t);
  306. }
  307. /*
  308. * Convert the byte order of the data we are looking at
  309. * While we're here, let's apply the mask operation
  310. * (unless you have a better idea)
  311. */
  312. private int
  313. mconvert(struct magic_set *ms, union VALUETYPE *p, struct magic *m)
  314. {
  315. switch (m->type) {
  316. case FILE_BYTE:
  317. if (m->mask)
  318. switch (m->mask_op & 0x7F) {
  319. case FILE_OPAND:
  320. p->b &= m->mask;
  321. break;
  322. case FILE_OPOR:
  323. p->b |= m->mask;
  324. break;
  325. case FILE_OPXOR:
  326. p->b ^= m->mask;
  327. break;
  328. case FILE_OPADD:
  329. p->b += m->mask;
  330. break;
  331. case FILE_OPMINUS:
  332. p->b -= m->mask;
  333. break;
  334. case FILE_OPMULTIPLY:
  335. p->b *= m->mask;
  336. break;
  337. case FILE_OPDIVIDE:
  338. p->b /= m->mask;
  339. break;
  340. case FILE_OPMODULO:
  341. p->b %= m->mask;
  342. break;
  343. }
  344. if (m->mask_op & FILE_OPINVERSE)
  345. p->b = ~p->b;
  346. return 1;
  347. case FILE_SHORT:
  348. if (m->mask)
  349. switch (m->mask_op & 0x7F) {
  350. case FILE_OPAND:
  351. p->h &= m->mask;
  352. break;
  353. case FILE_OPOR:
  354. p->h |= m->mask;
  355. break;
  356. case FILE_OPXOR:
  357. p->h ^= m->mask;
  358. break;
  359. case FILE_OPADD:
  360. p->h += m->mask;
  361. break;
  362. case FILE_OPMINUS:
  363. p->h -= m->mask;
  364. break;
  365. case FILE_OPMULTIPLY:
  366. p->h *= m->mask;
  367. break;
  368. case FILE_OPDIVIDE:
  369. p->h /= m->mask;
  370. break;
  371. case FILE_OPMODULO:
  372. p->h %= m->mask;
  373. break;
  374. }
  375. if (m->mask_op & FILE_OPINVERSE)
  376. p->h = ~p->h;
  377. return 1;
  378. case FILE_LONG:
  379. case FILE_DATE:
  380. case FILE_LDATE:
  381. if (m->mask)
  382. switch (m->mask_op & 0x7F) {
  383. case FILE_OPAND:
  384. p->l &= m->mask;
  385. break;
  386. case FILE_OPOR:
  387. p->l |= m->mask;
  388. break;
  389. case FILE_OPXOR:
  390. p->l ^= m->mask;
  391. break;
  392. case FILE_OPADD:
  393. p->l += m->mask;
  394. break;
  395. case FILE_OPMINUS:
  396. p->l -= m->mask;
  397. break;
  398. case FILE_OPMULTIPLY:
  399. p->l *= m->mask;
  400. break;
  401. case FILE_OPDIVIDE:
  402. p->l /= m->mask;
  403. break;
  404. case FILE_OPMODULO:
  405. p->l %= m->mask;
  406. break;
  407. }
  408. if (m->mask_op & FILE_OPINVERSE)
  409. p->l = ~p->l;
  410. return 1;
  411. case FILE_STRING:
  412. case FILE_BESTRING16:
  413. case FILE_LESTRING16:
  414. {
  415. size_t len;
  416. /* Null terminate and eat *trailing* return */
  417. p->s[sizeof(p->s) - 1] = '\0';
  418. len = strlen(p->s);
  419. if (len-- && p->s[len] == '\n')
  420. p->s[len] = '\0';
  421. return 1;
  422. }
  423. case FILE_PSTRING:
  424. {
  425. char *ptr1 = p->s, *ptr2 = ptr1 + 1;
  426. size_t len = *p->s;
  427. if (len >= sizeof(p->s))
  428. len = sizeof(p->s) - 1;
  429. while (len--)
  430. *ptr1++ = *ptr2++;
  431. *ptr1 = '\0';
  432. len = strlen(p->s);
  433. if (len-- && p->s[len] == '\n')
  434. p->s[len] = '\0';
  435. return 1;
  436. }
  437. case FILE_BESHORT:
  438. p->h = (short)((p->hs[0]<<8)|(p->hs[1]));
  439. if (m->mask)
  440. switch (m->mask_op&0x7F) {
  441. case FILE_OPAND:
  442. p->h &= m->mask;
  443. break;
  444. case FILE_OPOR:
  445. p->h |= m->mask;
  446. break;
  447. case FILE_OPXOR:
  448. p->h ^= m->mask;
  449. break;
  450. case FILE_OPADD:
  451. p->h += m->mask;
  452. break;
  453. case FILE_OPMINUS:
  454. p->h -= m->mask;
  455. break;
  456. case FILE_OPMULTIPLY:
  457. p->h *= m->mask;
  458. break;
  459. case FILE_OPDIVIDE:
  460. p->h /= m->mask;
  461. break;
  462. case FILE_OPMODULO:
  463. p->h %= m->mask;
  464. break;
  465. }
  466. if (m->mask_op & FILE_OPINVERSE)
  467. p->h = ~p->h;
  468. return 1;
  469. case FILE_BELONG:
  470. case FILE_BEDATE:
  471. case FILE_BELDATE:
  472. p->l = (int32_t)
  473. ((p->hl[0]<<24)|(p->hl[1]<<16)|(p->hl[2]<<8)|(p->hl[3]));
  474. if (m->mask)
  475. switch (m->mask_op&0x7F) {
  476. case FILE_OPAND:
  477. p->l &= m->mask;
  478. break;
  479. case FILE_OPOR:
  480. p->l |= m->mask;
  481. break;
  482. case FILE_OPXOR:
  483. p->l ^= m->mask;
  484. break;
  485. case FILE_OPADD:
  486. p->l += m->mask;
  487. break;
  488. case FILE_OPMINUS:
  489. p->l -= m->mask;
  490. break;
  491. case FILE_OPMULTIPLY:
  492. p->l *= m->mask;
  493. break;
  494. case FILE_OPDIVIDE:
  495. p->l /= m->mask;
  496. break;
  497. case FILE_OPMODULO:
  498. p->l %= m->mask;
  499. break;
  500. }
  501. if (m->mask_op & FILE_OPINVERSE)
  502. p->l = ~p->l;
  503. return 1;
  504. case FILE_LESHORT:
  505. p->h = (short)((p->hs[1]<<8)|(p->hs[0]));
  506. if (m->mask)
  507. switch (m->mask_op&0x7F) {
  508. case FILE_OPAND:
  509. p->h &= m->mask;
  510. break;
  511. case FILE_OPOR:
  512. p->h |= m->mask;
  513. break;
  514. case FILE_OPXOR:
  515. p->h ^= m->mask;
  516. break;
  517. case FILE_OPADD:
  518. p->h += m->mask;
  519. break;
  520. case FILE_OPMINUS:
  521. p->h -= m->mask;
  522. break;
  523. case FILE_OPMULTIPLY:
  524. p->h *= m->mask;
  525. break;
  526. case FILE_OPDIVIDE:
  527. p->h /= m->mask;
  528. break;
  529. case FILE_OPMODULO:
  530. p->h %= m->mask;
  531. break;
  532. }
  533. if (m->mask_op & FILE_OPINVERSE)
  534. p->h = ~p->h;
  535. return 1;
  536. case FILE_LELONG:
  537. case FILE_LEDATE:
  538. case FILE_LELDATE:
  539. p->l = (int32_t)
  540. ((p->hl[3]<<24)|(p->hl[2]<<16)|(p->hl[1]<<8)|(p->hl[0]));
  541. if (m->mask)
  542. switch (m->mask_op&0x7F) {
  543. case FILE_OPAND:
  544. p->l &= m->mask;
  545. break;
  546. case FILE_OPOR:
  547. p->l |= m->mask;
  548. break;
  549. case FILE_OPXOR:
  550. p->l ^= m->mask;
  551. break;
  552. case FILE_OPADD:
  553. p->l += m->mask;
  554. break;
  555. case FILE_OPMINUS:
  556. p->l -= m->mask;
  557. break;
  558. case FILE_OPMULTIPLY:
  559. p->l *= m->mask;
  560. break;
  561. case FILE_OPDIVIDE:
  562. p->l /= m->mask;
  563. break;
  564. case FILE_OPMODULO:
  565. p->l %= m->mask;
  566. break;
  567. }
  568. if (m->mask_op & FILE_OPINVERSE)
  569. p->l = ~p->l;
  570. return 1;
  571. case FILE_REGEX:
  572. case FILE_SEARCH:
  573. return 1;
  574. default:
  575. file_error(ms, 0, "invalid type %d in mconvert()", m->type);
  576. return 0;
  577. }
  578. }
  579. private void
  580. mdebug(uint32_t offset, const char *str, size_t len)
  581. {
  582. (void) fprintf(stderr, "mget @%d: ", offset);
  583. file_showstr(stderr, str, len);
  584. (void) fputc('\n', stderr);
  585. (void) fputc('\n', stderr);
  586. }
  587. private int
  588. mcopy(struct magic_set *ms, union VALUETYPE *p, int type, int indir,
  589. const unsigned char *s, size_t offset, size_t nbytes)
  590. {
  591. if (type == FILE_REGEX && indir == 0) {
  592. /*
  593. * offset is interpreted as last line to search,
  594. * (starting at 1), not as bytes-from start-of-file
  595. */
  596. char *b, *c, *last = NULL;
  597. if ((p->search.buf = strdup((const char *)s)) == NULL) {
  598. file_oomem(ms);
  599. return -1;
  600. }
  601. for (b = p->search.buf; offset &&
  602. ((b = strchr(c = b, '\n')) || (b = strchr(c, '\r')));
  603. offset--, b++) {
  604. last = b;
  605. if (b[0] == '\r' && b[1] == '\n') b++;
  606. }
  607. if (last != NULL)
  608. *last = '\0';
  609. p->search.buflen = last - p->search.buf;
  610. return 0;
  611. }
  612. if (indir == 0 && (type == FILE_BESTRING16 || type == FILE_LESTRING16))
  613. {
  614. const char *src = s + offset;
  615. const char *esrc = s + nbytes;
  616. char *dst = p->s, *edst = &p->s[sizeof(p->s) - 1];
  617. if (type == FILE_BESTRING16)
  618. src++;
  619. for (;src < esrc; src++, dst++) {
  620. if (dst < edst)
  621. *dst = *src++;
  622. else
  623. break;
  624. if (*dst == '\0')
  625. *dst = ' ';
  626. }
  627. *edst = '\0';
  628. return 0;
  629. }
  630. if (offset >= nbytes) {
  631. (void)memset(p, '\0', sizeof(*p));
  632. return 0;
  633. }
  634. if (nbytes - offset < sizeof(*p))
  635. nbytes = nbytes - offset;
  636. else
  637. nbytes = sizeof(*p);
  638. (void)memcpy(p, s + offset, nbytes);
  639. /*
  640. * the usefulness of padding with zeroes eludes me, it
  641. * might even cause problems
  642. */
  643. if (nbytes < sizeof(*p))
  644. (void)memset(((char *)p) + nbytes, '\0', sizeof(*p) - nbytes);
  645. return 0;
  646. }
  647. private int
  648. mget(struct magic_set *ms, union VALUETYPE *p, const unsigned char *s,
  649. struct magic *m, size_t nbytes, int cont_level)
  650. {
  651. uint32_t offset = m->offset;
  652. if (mcopy(ms, p, m->type, m->flag & INDIR, s, offset, nbytes) == -1)
  653. return -1;
  654. if ((ms->flags & MAGIC_DEBUG) != 0) {
  655. mdebug(offset, (char *)(void *)p, sizeof(union VALUETYPE));
  656. file_mdump(m);
  657. }
  658. if (m->flag & INDIR) {
  659. int off = m->in_offset;
  660. if (m->in_op & FILE_OPINDIRECT) {
  661. const union VALUETYPE *q =
  662. ((const union VALUETYPE *)(s + offset + off));
  663. switch (m->in_type) {
  664. case FILE_BYTE:
  665. off = q->b;
  666. break;
  667. case FILE_SHORT:
  668. off = q->h;
  669. break;
  670. case FILE_BESHORT:
  671. off = (short)((q->hs[0]<<8)|(q->hs[1]));
  672. break;
  673. case FILE_LESHORT:
  674. off = (short)((q->hs[1]<<8)|(q->hs[0]));
  675. break;
  676. case FILE_LONG:
  677. off = q->l;
  678. break;
  679. case FILE_BELONG:
  680. off = (int32_t)((q->hl[0]<<24)|(q->hl[1]<<16)|
  681. (q->hl[2]<<8)|(q->hl[3]));
  682. break;
  683. case FILE_LELONG:
  684. off = (int32_t)((q->hl[3]<<24)|(q->hl[2]<<16)|
  685. (q->hl[1]<<8)|(q->hl[0]));
  686. break;
  687. }
  688. }
  689. switch (m->in_type) {
  690. case FILE_BYTE:
  691. if (nbytes < (offset + 1)) return 0;
  692. if (off) {
  693. switch (m->in_op & 0x3F) {
  694. case FILE_OPAND:
  695. offset = p->b & off;
  696. break;
  697. case FILE_OPOR:
  698. offset = p->b | off;
  699. break;
  700. case FILE_OPXOR:
  701. offset = p->b ^ off;
  702. break;
  703. case FILE_OPADD:
  704. offset = p->b + off;
  705. break;
  706. case FILE_OPMINUS:
  707. offset = p->b - off;
  708. break;
  709. case FILE_OPMULTIPLY:
  710. offset = p->b * off;
  711. break;
  712. case FILE_OPDIVIDE:
  713. offset = p->b / off;
  714. break;
  715. case FILE_OPMODULO:
  716. offset = p->b % off;
  717. break;
  718. }
  719. } else
  720. offset = p->b;
  721. if (m->in_op & FILE_OPINVERSE)
  722. offset = ~offset;
  723. break;
  724. case FILE_BESHORT:
  725. if (nbytes < (offset + 2))
  726. return 0;
  727. if (off) {
  728. switch (m->in_op & 0x7F) {
  729. case FILE_OPAND:
  730. offset = (short)((p->hs[0]<<8)|
  731. (p->hs[1])) &
  732. off;
  733. break;
  734. case FILE_OPOR:
  735. offset = (short)((p->hs[0]<<8)|
  736. (p->hs[1])) |
  737. off;
  738. break;
  739. case FILE_OPXOR:
  740. offset = (short)((p->hs[0]<<8)|
  741. (p->hs[1])) ^
  742. off;
  743. break;
  744. case FILE_OPADD:
  745. offset = (short)((p->hs[0]<<8)|
  746. (p->hs[1])) +
  747. off;
  748. break;
  749. case FILE_OPMINUS:
  750. offset = (short)((p->hs[0]<<8)|
  751. (p->hs[1])) -
  752. off;
  753. break;
  754. case FILE_OPMULTIPLY:
  755. offset = (short)((p->hs[0]<<8)|
  756. (p->hs[1])) *
  757. off;
  758. break;
  759. case FILE_OPDIVIDE:
  760. offset = (short)((p->hs[0]<<8)|
  761. (p->hs[1])) /
  762. off;
  763. break;
  764. case FILE_OPMODULO:
  765. offset = (short)((p->hs[0]<<8)|
  766. (p->hs[1])) %
  767. off;
  768. break;
  769. }
  770. } else
  771. offset = (short)((p->hs[0]<<8)|
  772. (p->hs[1]));
  773. if (m->in_op & FILE_OPINVERSE)
  774. offset = ~offset;
  775. break;
  776. case FILE_LESHORT:
  777. if (nbytes < (offset + 2))
  778. return 0;
  779. if (off) {
  780. switch (m->in_op & 0x7F) {
  781. case FILE_OPAND:
  782. offset = (short)((p->hs[1]<<8)|
  783. (p->hs[0])) &
  784. off;
  785. break;
  786. case FILE_OPOR:
  787. offset = (short)((p->hs[1]<<8)|
  788. (p->hs[0])) |
  789. off;
  790. break;
  791. case FILE_OPXOR:
  792. offset = (short)((p->hs[1]<<8)|
  793. (p->hs[0])) ^
  794. off;
  795. break;
  796. case FILE_OPADD:
  797. offset = (short)((p->hs[1]<<8)|
  798. (p->hs[0])) +
  799. off;
  800. break;
  801. case FILE_OPMINUS:
  802. offset = (short)((p->hs[1]<<8)|
  803. (p->hs[0])) -
  804. off;
  805. break;
  806. case FILE_OPMULTIPLY:
  807. offset = (short)((p->hs[1]<<8)|
  808. (p->hs[0])) *
  809. off;
  810. break;
  811. case FILE_OPDIVIDE:
  812. offset = (short)((p->hs[1]<<8)|
  813. (p->hs[0])) /
  814. off;
  815. break;
  816. case FILE_OPMODULO:
  817. offset = (short)((p->hs[1]<<8)|
  818. (p->hs[0])) %
  819. off;
  820. break;
  821. }
  822. } else
  823. offset = (short)((p->hs[1]<<8)|
  824. (p->hs[0]));
  825. if (m->in_op & FILE_OPINVERSE)
  826. offset = ~offset;
  827. break;
  828. case FILE_SHORT:
  829. if (nbytes < (offset + 2))
  830. return 0;
  831. if (off) {
  832. switch (m->in_op & 0x7F) {
  833. case FILE_OPAND:
  834. offset = p->h & off;
  835. break;
  836. case FILE_OPOR:
  837. offset = p->h | off;
  838. break;
  839. case FILE_OPXOR:
  840. offset = p->h ^ off;
  841. break;
  842. case FILE_OPADD:
  843. offset = p->h + off;
  844. break;
  845. case FILE_OPMINUS:
  846. offset = p->h - off;
  847. break;
  848. case FILE_OPMULTIPLY:
  849. offset = p->h * off;
  850. break;
  851. case FILE_OPDIVIDE:
  852. offset = p->h / off;
  853. break;
  854. case FILE_OPMODULO:
  855. offset = p->h % off;
  856. break;
  857. }
  858. }
  859. else
  860. offset = p->h;
  861. if (m->in_op & FILE_OPINVERSE)
  862. offset = ~offset;
  863. break;
  864. case FILE_BELONG:
  865. if (nbytes < (offset + 4))
  866. return 0;
  867. if (off) {
  868. switch (m->in_op & 0x7F) {
  869. case FILE_OPAND:
  870. offset = (int32_t)((p->hl[0]<<24)|
  871. (p->hl[1]<<16)|
  872. (p->hl[2]<<8)|
  873. (p->hl[3])) &
  874. off;
  875. break;
  876. case FILE_OPOR:
  877. offset = (int32_t)((p->hl[0]<<24)|
  878. (p->hl[1]<<16)|
  879. (p->hl[2]<<8)|
  880. (p->hl[3])) |
  881. off;
  882. break;
  883. case FILE_OPXOR:
  884. offset = (int32_t)((p->hl[0]<<24)|
  885. (p->hl[1]<<16)|
  886. (p->hl[2]<<8)|
  887. (p->hl[3])) ^
  888. off;
  889. break;
  890. case FILE_OPADD:
  891. offset = (int32_t)((p->hl[0]<<24)|
  892. (p->hl[1]<<16)|
  893. (p->hl[2]<<8)|
  894. (p->hl[3])) +
  895. off;
  896. break;
  897. case FILE_OPMINUS:
  898. offset = (int32_t)((p->hl[0]<<24)|
  899. (p->hl[1]<<16)|
  900. (p->hl[2]<<8)|
  901. (p->hl[3])) -
  902. off;
  903. break;
  904. case FILE_OPMULTIPLY:
  905. offset = (int32_t)((p->hl[0]<<24)|
  906. (p->hl[1]<<16)|
  907. (p->hl[2]<<8)|
  908. (p->hl[3])) *
  909. off;
  910. break;
  911. case FILE_OPDIVIDE:
  912. offset = (int32_t)((p->hl[0]<<24)|
  913. (p->hl[1]<<16)|
  914. (p->hl[2]<<8)|
  915. (p->hl[3])) /
  916. off;
  917. break;
  918. case FILE_OPMODULO:
  919. offset = (int32_t)((p->hl[0]<<24)|
  920. (p->hl[1]<<16)|
  921. (p->hl[2]<<8)|
  922. (p->hl[3])) %
  923. off;
  924. break;
  925. }
  926. } else
  927. offset = (int32_t)((p->hl[0]<<24)|
  928. (p->hl[1]<<16)|
  929. (p->hl[2]<<8)|
  930. (p->hl[3]));
  931. if (m->in_op & FILE_OPINVERSE)
  932. offset = ~offset;
  933. break;
  934. case FILE_LELONG:
  935. if (nbytes < (offset + 4))
  936. return 0;
  937. if (off) {
  938. switch (m->in_op & 0x7F) {
  939. case FILE_OPAND:
  940. offset = (int32_t)((p->hl[3]<<24)|
  941. (p->hl[2]<<16)|
  942. (p->hl[1]<<8)|
  943. (p->hl[0])) &
  944. off;
  945. break;
  946. case FILE_OPOR:
  947. offset = (int32_t)((p->hl[3]<<24)|
  948. (p->hl[2]<<16)|
  949. (p->hl[1]<<8)|
  950. (p->hl[0])) |
  951. off;
  952. break;
  953. case FILE_OPXOR:
  954. offset = (int32_t)((p->hl[3]<<24)|
  955. (p->hl[2]<<16)|
  956. (p->hl[1]<<8)|
  957. (p->hl[0])) ^
  958. off;
  959. break;
  960. case FILE_OPADD:
  961. offset = (int32_t)((p->hl[3]<<24)|
  962. (p->hl[2]<<16)|
  963. (p->hl[1]<<8)|
  964. (p->hl[0])) +
  965. off;
  966. break;
  967. case FILE_OPMINUS:
  968. offset = (int32_t)((p->hl[3]<<24)|
  969. (p->hl[2]<<16)|
  970. (p->hl[1]<<8)|
  971. (p->hl[0])) -
  972. off;
  973. break;
  974. case FILE_OPMULTIPLY:
  975. offset = (int32_t)((p->hl[3]<<24)|
  976. (p->hl[2]<<16)|
  977. (p->hl[1]<<8)|
  978. (p->hl[0])) *
  979. off;
  980. break;
  981. case FILE_OPDIVIDE:
  982. offset = (int32_t)((p->hl[3]<<24)|
  983. (p->hl[2]<<16)|
  984. (p->hl[1]<<8)|
  985. (p->hl[0])) /
  986. off;
  987. break;
  988. case FILE_OPMODULO:
  989. offset = (int32_t)((p->hl[3]<<24)|
  990. (p->hl[2]<<16)|
  991. (p->hl[1]<<8)|
  992. (p->hl[0])) %
  993. off;
  994. break;
  995. }
  996. } else
  997. offset = (int32_t)((p->hl[3]<<24)|
  998. (p->hl[2]<<16)|
  999. (p->hl[1]<<8)|
  1000. (p->hl[0]));
  1001. if (m->in_op & FILE_OPINVERSE)
  1002. offset = ~offset;
  1003. break;
  1004. case FILE_LONG:
  1005. if (nbytes < (offset + 4))
  1006. return 0;
  1007. if (off) {
  1008. switch (m->in_op & 0x7F) {
  1009. case FILE_OPAND:
  1010. offset = p->l & off;
  1011. break;
  1012. case FILE_OPOR:
  1013. offset = p->l | off;
  1014. break;
  1015. case FILE_OPXOR:
  1016. offset = p->l ^ off;
  1017. break;
  1018. case FILE_OPADD:
  1019. offset = p->l + off;
  1020. break;
  1021. case FILE_OPMINUS:
  1022. offset = p->l - off;
  1023. break;
  1024. case FILE_OPMULTIPLY:
  1025. offset = p->l * off;
  1026. break;
  1027. case FILE_OPDIVIDE:
  1028. offset = p->l / off;
  1029. break;
  1030. case FILE_OPMODULO:
  1031. offset = p->l % off;
  1032. break;
  1033. /* case TOOMANYSWITCHBLOCKS:
  1034. * ugh = p->eye % m->strain;
  1035. * rub;
  1036. * case BEER:
  1037. * off = p->tab & m->in_gest;
  1038. * sleep;
  1039. */
  1040. }
  1041. } else
  1042. offset = p->l;
  1043. if (m->in_op & FILE_OPINVERSE)
  1044. offset = ~offset;
  1045. break;
  1046. }
  1047. if (m->flag & INDIROFFADD) offset += ms->c.off[cont_level-1];
  1048. if (mcopy(ms, p, m->type, 0, s, offset, nbytes) == -1)
  1049. return -1;
  1050. m->offset = offset;
  1051. if ((ms->flags & MAGIC_DEBUG) != 0) {
  1052. mdebug(offset, (char *)(void *)p,
  1053. sizeof(union VALUETYPE));
  1054. file_mdump(m);
  1055. }
  1056. }
  1057. /* Verify we have enough data to match magic type */
  1058. switch (m->type) {
  1059. case FILE_BYTE:
  1060. if (nbytes < (offset + 1)) /* should alway be true */
  1061. return 0;
  1062. break;
  1063. case FILE_SHORT:
  1064. case FILE_BESHORT:
  1065. case FILE_LESHORT:
  1066. if (nbytes < (offset + 2))
  1067. return 0;
  1068. break;
  1069. case FILE_LONG:
  1070. case FILE_BELONG:
  1071. case FILE_LELONG:
  1072. case FILE_DATE:
  1073. case FILE_BEDATE:
  1074. case FILE_LEDATE:
  1075. case FILE_LDATE:
  1076. case FILE_BELDATE:
  1077. case FILE_LELDATE:
  1078. if (nbytes < (offset + 4))
  1079. return 0;
  1080. break;
  1081. case FILE_STRING:
  1082. case FILE_PSTRING:
  1083. case FILE_SEARCH:
  1084. if (nbytes < (offset + m->vallen))
  1085. return 0;
  1086. break;
  1087. default: break;
  1088. }
  1089. if (m->type == FILE_SEARCH) {
  1090. size_t mlen = m->mask + m->vallen;
  1091. size_t flen = nbytes - offset;
  1092. if (flen < mlen)
  1093. mlen = flen;
  1094. p->search.buflen = mlen;
  1095. p->search.buf = malloc(mlen + 1);
  1096. if (p->search.buf == NULL) {
  1097. file_error(ms, errno, "Cannot allocate search buffer");
  1098. return 0;
  1099. }
  1100. (void)memcpy(p->search.buf, s + offset, mlen);
  1101. p->search.buf[mlen] = '\0';
  1102. }
  1103. if (!mconvert(ms, p, m))
  1104. return 0;
  1105. return 1;
  1106. }
  1107. private int
  1108. mcheck(struct magic_set *ms, union VALUETYPE *p, struct magic *m)
  1109. {
  1110. uint32_t l = m->value.l;
  1111. uint32_t v;
  1112. int matched;
  1113. if ( (m->value.s[0] == 'x') && (m->value.s[1] == '\0') ) {
  1114. return 1;
  1115. }
  1116. switch (m->type) {
  1117. case FILE_BYTE:
  1118. v = p->b;
  1119. break;
  1120. case FILE_SHORT:
  1121. case FILE_BESHORT:
  1122. case FILE_LESHORT:
  1123. v = p->h;
  1124. break;
  1125. case FILE_LONG:
  1126. case FILE_BELONG:
  1127. case FILE_LELONG:
  1128. case FILE_DATE:
  1129. case FILE_BEDATE:
  1130. case FILE_LEDATE:
  1131. case FILE_LDATE:
  1132. case FILE_BELDATE:
  1133. case FILE_LELDATE:
  1134. v = p->l;
  1135. break;
  1136. case FILE_STRING:
  1137. case FILE_BESTRING16:
  1138. case FILE_LESTRING16:
  1139. case FILE_PSTRING:
  1140. {
  1141. /*
  1142. * What we want here is:
  1143. * v = strncmp(m->value.s, p->s, m->vallen);
  1144. * but ignoring any nulls. bcmp doesn't give -/+/0
  1145. * and isn't universally available anyway.
  1146. */
  1147. unsigned char *a = (unsigned char*)m->value.s;
  1148. unsigned char *b = (unsigned char*)p->s;
  1149. int len = m->vallen;
  1150. l = 0;
  1151. v = 0;
  1152. if (0L == m->mask) { /* normal string: do it fast */
  1153. while (--len >= 0)
  1154. if ((v = *b++ - *a++) != '\0')
  1155. break;
  1156. } else { /* combine the others */
  1157. while (--len >= 0) {
  1158. if ((m->mask & STRING_IGNORE_LOWERCASE) &&
  1159. islower(*a)) {
  1160. if ((v = tolower(*b++) - *a++) != '\0')
  1161. break;
  1162. } else if ((m->mask & STRING_COMPACT_BLANK) &&
  1163. isspace(*a)) {
  1164. a++;
  1165. if (isspace(*b++)) {
  1166. while (isspace(*b))
  1167. b++;
  1168. } else {
  1169. v = 1;
  1170. break;
  1171. }
  1172. } else if (isspace(*a) &&
  1173. (m->mask & STRING_COMPACT_OPTIONAL_BLANK)) {
  1174. a++;
  1175. while (isspace(*b))
  1176. b++;
  1177. } else {
  1178. if ((v = *b++ - *a++) != '\0')
  1179. break;
  1180. }
  1181. }
  1182. }
  1183. break;
  1184. }
  1185. case FILE_REGEX:
  1186. {
  1187. int rc;
  1188. regex_t rx;
  1189. char errmsg[512];
  1190. if (p->search.buf == NULL)
  1191. return 0;
  1192. rc = regcomp(&rx, m->value.s,
  1193. REG_EXTENDED|REG_NOSUB|REG_NEWLINE|
  1194. ((m->mask & STRING_IGNORE_LOWERCASE) ? REG_ICASE : 0));
  1195. if (rc) {
  1196. free(p->search.buf);
  1197. p->search.buf = NULL;
  1198. regerror(rc, &rx, errmsg, sizeof(errmsg));
  1199. file_error(ms, 0, "regex error %d, (%s)", rc, errmsg);
  1200. return -1;
  1201. } else {
  1202. rc = regexec(&rx, p->search.buf, 0, 0, 0);
  1203. regfree(&rx);
  1204. free(p->search.buf);
  1205. p->search.buf = NULL;
  1206. return !rc;
  1207. }
  1208. }
  1209. case FILE_SEARCH:
  1210. {
  1211. /*
  1212. * search for a string in a certain range
  1213. */
  1214. unsigned char *a = (unsigned char*)m->value.s;
  1215. unsigned char *b = (unsigned char*)p->search.buf;
  1216. size_t len, slen = m->vallen;
  1217. size_t range = 0;
  1218. if (slen > sizeof(m->value.s))
  1219. slen = sizeof(m->value.s);
  1220. l = 0;
  1221. v = 0;
  1222. if (b == NULL)
  1223. return 0;
  1224. len = slen;
  1225. while (++range <= m->mask) {
  1226. while (len-- > 0 && (v = *b++ - *a++) == 0)
  1227. continue;
  1228. if (!v) {
  1229. m->offset += range - 1;
  1230. break;
  1231. }
  1232. if (range + slen >= p->search.buflen)
  1233. break;
  1234. len = slen;
  1235. a = (unsigned char*)m->value.s;
  1236. b = (unsigned char*)p->search.buf + range;
  1237. }
  1238. free(p->search.buf);
  1239. p->search.buf = NULL;
  1240. break;
  1241. }
  1242. default:
  1243. file_error(ms, 0, "invalid type %d in mcheck()", m->type);
  1244. return -1;
  1245. }
  1246. if (m->type != FILE_STRING && m->type != FILE_PSTRING)
  1247. v = file_signextend(ms, m, v);
  1248. switch (m->reln) {
  1249. case 'x':
  1250. if ((ms->flags & MAGIC_DEBUG) != 0)
  1251. (void) fprintf(stderr, "%u == *any* = 1\n", v);
  1252. matched = 1;
  1253. break;
  1254. case '!':
  1255. matched = v != l;
  1256. if ((ms->flags & MAGIC_DEBUG) != 0)
  1257. (void) fprintf(stderr, "%u != %u = %d\n",
  1258. v, l, matched);
  1259. break;
  1260. case '=':
  1261. matched = v == l;
  1262. if ((ms->flags & MAGIC_DEBUG) != 0)
  1263. (void) fprintf(stderr, "%u == %u = %d\n",
  1264. v, l, matched);
  1265. break;
  1266. case '>':
  1267. if (m->flag & UNSIGNED) {
  1268. matched = v > l;
  1269. if ((ms->flags & MAGIC_DEBUG) != 0)
  1270. (void) fprintf(stderr, "%u > %u = %d\n",
  1271. v, l, matched);
  1272. }
  1273. else {
  1274. matched = (int32_t) v > (int32_t) l;
  1275. if ((ms->flags & MAGIC_DEBUG) != 0)
  1276. (void) fprintf(stderr, "%d > %d = %d\n",
  1277. v, l, matched);
  1278. }
  1279. break;
  1280. case '<':
  1281. if (m->flag & UNSIGNED) {
  1282. matched = v < l;
  1283. if ((ms->flags & MAGIC_DEBUG) != 0)
  1284. (void) fprintf(stderr, "%u < %u = %d\n",
  1285. v, l, matched);
  1286. }
  1287. else {
  1288. matched = (int32_t) v < (int32_t) l;
  1289. if ((ms->flags & MAGIC_DEBUG) != 0)
  1290. (void) fprintf(stderr, "%d < %d = %d\n",
  1291. v, l, matched);
  1292. }
  1293. break;
  1294. case '&':
  1295. matched = (v & l) == l;
  1296. if ((ms->flags & MAGIC_DEBUG) != 0)
  1297. (void) fprintf(stderr, "((%x & %x) == %x) = %d\n",
  1298. v, l, l, matched);
  1299. break;
  1300. case '^':
  1301. matched = (v & l) != l;
  1302. if ((ms->flags & MAGIC_DEBUG) != 0)
  1303. (void) fprintf(stderr, "((%x & %x) != %x) = %d\n",
  1304. v, l, l, matched);
  1305. break;
  1306. default:
  1307. matched = 0;
  1308. file_error(ms, 0, "cannot happen: invalid relation `%c'",
  1309. m->reln);
  1310. return -1;
  1311. }
  1312. return matched;
  1313. }