softmagic.c 34 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507
  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.87 2006/12/11 21:48:49 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, unsigned int);
  45. private int magiccheck(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 *, uint32_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. private int print_sep(struct magic_set *, int);
  53. private void cvt_8(union VALUETYPE *, const struct magic *);
  54. private void cvt_16(union VALUETYPE *, const struct magic *);
  55. private void cvt_32(union VALUETYPE *, const struct magic *);
  56. private void cvt_64(union VALUETYPE *, const struct magic *);
  57. /*
  58. * softmagic - lookup one file in parsed, in-memory copy of database
  59. * Passed the name and FILE * of one file to be typed.
  60. */
  61. /*ARGSUSED1*/ /* nbytes passed for regularity, maybe need later */
  62. protected int
  63. file_softmagic(struct magic_set *ms, const unsigned char *buf, size_t nbytes)
  64. {
  65. struct mlist *ml;
  66. int rv;
  67. for (ml = ms->mlist->next; ml != ms->mlist; ml = ml->next)
  68. if ((rv = match(ms, ml->magic, ml->nmagic, buf, nbytes)) != 0)
  69. return rv;
  70. return 0;
  71. }
  72. /*
  73. * Go through the whole list, stopping if you find a match. Process all
  74. * the continuations of that match before returning.
  75. *
  76. * We support multi-level continuations:
  77. *
  78. * At any time when processing a successful top-level match, there is a
  79. * current continuation level; it represents the level of the last
  80. * successfully matched continuation.
  81. *
  82. * Continuations above that level are skipped as, if we see one, it
  83. * means that the continuation that controls them - i.e, the
  84. * lower-level continuation preceding them - failed to match.
  85. *
  86. * Continuations below that level are processed as, if we see one,
  87. * it means we've finished processing or skipping higher-level
  88. * continuations under the control of a successful or unsuccessful
  89. * lower-level continuation, and are now seeing the next lower-level
  90. * continuation and should process it. The current continuation
  91. * level reverts to the level of the one we're seeing.
  92. *
  93. * Continuations at the current level are processed as, if we see
  94. * one, there's no lower-level continuation that may have failed.
  95. *
  96. * If a continuation matches, we bump the current continuation level
  97. * so that higher-level continuations are processed.
  98. */
  99. private int
  100. match(struct magic_set *ms, struct magic *magic, uint32_t nmagic,
  101. const unsigned char *s, size_t nbytes)
  102. {
  103. uint32_t magindex = 0;
  104. unsigned int cont_level = 0;
  105. int need_separator = 0;
  106. union VALUETYPE p;
  107. int32_t oldoff = 0;
  108. int returnval = 0; /* if a match is found it is set to 1*/
  109. int firstline = 1; /* a flag to print X\n X\n- X */
  110. int printed_something = 0;
  111. if (check_mem(ms, cont_level) == -1)
  112. return -1;
  113. for (magindex = 0; magindex < nmagic; magindex++) {
  114. /* if main entry matches, print it... */
  115. ms->offset = magic[magindex].offset;
  116. int flush = !mget(ms, &p, s, &magic[magindex], nbytes,
  117. cont_level);
  118. if (flush) {
  119. if (magic[magindex].reln == '!')
  120. flush = 0;
  121. } else {
  122. switch (magiccheck(ms, &p, &magic[magindex])) {
  123. case -1:
  124. return -1;
  125. case 0:
  126. flush++;
  127. break;
  128. default:
  129. break;
  130. }
  131. }
  132. if (flush) {
  133. /*
  134. * main entry didn't match,
  135. * flush its continuations
  136. */
  137. while (magindex < nmagic - 1 &&
  138. magic[magindex + 1].cont_level != 0)
  139. magindex++;
  140. continue;
  141. }
  142. /*
  143. * If we are going to print 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. printed_something = 1;
  149. if (print_sep(ms, firstline) == -1)
  150. return -1;
  151. }
  152. if ((ms->c.off[cont_level] = mprint(ms, &p, &magic[magindex]))
  153. == -1)
  154. return -1;
  155. /* and any continuations that match */
  156. if (check_mem(ms, ++cont_level) == -1)
  157. return -1;
  158. while (magic[magindex+1].cont_level != 0 &&
  159. ++magindex < nmagic) {
  160. if (cont_level < magic[magindex].cont_level)
  161. continue;
  162. if (cont_level > magic[magindex].cont_level) {
  163. /*
  164. * We're at the end of the level
  165. * "cont_level" continuations.
  166. */
  167. cont_level = magic[magindex].cont_level;
  168. }
  169. ms->offset = magic[magindex].offset;
  170. if (magic[magindex].flag & OFFADD) {
  171. ms->offset +=
  172. ms->c.off[cont_level - 1];
  173. }
  174. flush = !mget(ms, &p, s, &magic[magindex], nbytes,
  175. cont_level);
  176. if (flush && magic[magindex].reln != '!')
  177. continue;
  178. switch (flush ? 1 : magiccheck(ms, &p, &magic[magindex])) {
  179. case -1:
  180. return -1;
  181. case 0:
  182. break;
  183. default:
  184. /*
  185. * If we are going to print something,
  186. * make sure that we have a separator first.
  187. */
  188. if (magic[magindex].desc[0]) {
  189. printed_something = 1;
  190. if (print_sep(ms, firstline) == -1)
  191. return -1;
  192. }
  193. /*
  194. * This continuation matched.
  195. * Print its message, with
  196. * a blank before it if
  197. * the previous item printed
  198. * and this item isn't empty.
  199. */
  200. /* space if previous printed */
  201. if (need_separator
  202. && (magic[magindex].nospflag == 0)
  203. && (magic[magindex].desc[0] != '\0')) {
  204. if (file_printf(ms, " ") == -1)
  205. return -1;
  206. need_separator = 0;
  207. }
  208. if ((ms->c.off[cont_level] = mprint(ms, &p,
  209. &magic[magindex])) == -1)
  210. return -1;
  211. if (magic[magindex].desc[0])
  212. need_separator = 1;
  213. /*
  214. * If we see any continuations
  215. * at a higher level,
  216. * process them.
  217. */
  218. if (check_mem(ms, ++cont_level) == -1)
  219. return -1;
  220. }
  221. }
  222. firstline = 0;
  223. if (printed_something)
  224. returnval = 1;
  225. if ((ms->flags & MAGIC_CONTINUE) == 0 && printed_something) {
  226. return 1; /* don't keep searching */
  227. }
  228. }
  229. return returnval; /* This is hit if -k is set or there is no match */
  230. }
  231. private int
  232. check_mem(struct magic_set *ms, unsigned int level)
  233. {
  234. size_t len;
  235. if (level < ms->c.len)
  236. return 0;
  237. len = (ms->c.len += 20) * sizeof(*ms->c.off);
  238. ms->c.off = (ms->c.off == NULL) ? malloc(len) : realloc(ms->c.off, len);
  239. if (ms->c.off != NULL)
  240. return 0;
  241. file_oomem(ms, len);
  242. return -1;
  243. }
  244. private int
  245. check_fmt(struct magic_set *ms, struct magic *m)
  246. {
  247. regex_t rx;
  248. int rc;
  249. if (strchr(m->desc, '%') == NULL)
  250. return 0;
  251. rc = regcomp(&rx, "%[-0-9\\.]*s", REG_EXTENDED|REG_NOSUB);
  252. if (rc) {
  253. char errmsg[512];
  254. regerror(rc, &rx, errmsg, sizeof(errmsg));
  255. file_error(ms, 0, "regex error %d, (%s)", rc, errmsg);
  256. return -1;
  257. } else {
  258. rc = regexec(&rx, m->desc, 0, 0, 0);
  259. regfree(&rx);
  260. return !rc;
  261. }
  262. }
  263. private int32_t
  264. mprint(struct magic_set *ms, union VALUETYPE *p, struct magic *m)
  265. {
  266. uint64_t v;
  267. int32_t t = 0;
  268. char buf[512];
  269. switch (m->type) {
  270. case FILE_BYTE:
  271. v = file_signextend(ms, m, (uint64_t)p->b);
  272. switch (check_fmt(ms, m)) {
  273. case -1:
  274. return -1;
  275. case 1:
  276. if (snprintf(buf, sizeof(buf), "%c",
  277. (unsigned char)v) < 0)
  278. return -1;
  279. if (file_printf(ms, m->desc, buf) == -1)
  280. return -1;
  281. break;
  282. default:
  283. if (file_printf(ms, m->desc, (unsigned char) v) == -1)
  284. return -1;
  285. break;
  286. }
  287. t = ms->offset + sizeof(char);
  288. break;
  289. case FILE_SHORT:
  290. case FILE_BESHORT:
  291. case FILE_LESHORT:
  292. v = file_signextend(ms, m, (uint64_t)p->h);
  293. switch (check_fmt(ms, m)) {
  294. case -1:
  295. return -1;
  296. case 1:
  297. if (snprintf(buf, sizeof(buf), "%hu",
  298. (unsigned short)v) < 0)
  299. return -1;
  300. if (file_printf(ms, m->desc, buf) == -1)
  301. return -1;
  302. break;
  303. default:
  304. if (file_printf(ms, m->desc, (unsigned short) v) == -1)
  305. return -1;
  306. break;
  307. }
  308. t = ms->offset + sizeof(short);
  309. break;
  310. case FILE_LONG:
  311. case FILE_BELONG:
  312. case FILE_LELONG:
  313. case FILE_MELONG:
  314. v = file_signextend(ms, m, (uint64_t)p->l);
  315. switch (check_fmt(ms, m)) {
  316. case -1:
  317. return -1;
  318. case 1:
  319. if (snprintf(buf, sizeof(buf), "%u", (uint32_t)v) < 0)
  320. return -1;
  321. if (file_printf(ms, m->desc, buf) == -1)
  322. return -1;
  323. break;
  324. default:
  325. if (file_printf(ms, m->desc, (uint32_t) v) == -1)
  326. return -1;
  327. break;
  328. }
  329. t = ms->offset + sizeof(int32_t);
  330. break;
  331. case FILE_QUAD:
  332. case FILE_BEQUAD:
  333. case FILE_LEQUAD:
  334. v = file_signextend(ms, m, p->q);
  335. if (file_printf(ms, m->desc, (uint64_t) v) == -1)
  336. return -1;
  337. t = ms->offset + sizeof(int64_t);
  338. break;
  339. case FILE_STRING:
  340. case FILE_PSTRING:
  341. case FILE_BESTRING16:
  342. case FILE_LESTRING16:
  343. if (m->reln == '=' || m->reln == '!') {
  344. if (file_printf(ms, m->desc, m->value.s) == -1)
  345. return -1;
  346. t = ms->offset + m->vallen;
  347. }
  348. else {
  349. if (*m->value.s == '\0') {
  350. char *cp = strchr(p->s,'\n');
  351. if (cp)
  352. *cp = '\0';
  353. }
  354. if (file_printf(ms, m->desc, p->s) == -1)
  355. return -1;
  356. t = ms->offset + strlen(p->s);
  357. }
  358. break;
  359. case FILE_DATE:
  360. case FILE_BEDATE:
  361. case FILE_LEDATE:
  362. case FILE_MEDATE:
  363. if (file_printf(ms, m->desc, file_fmttime(p->l, 1)) == -1)
  364. return -1;
  365. t = ms->offset + sizeof(time_t);
  366. break;
  367. case FILE_LDATE:
  368. case FILE_BELDATE:
  369. case FILE_LELDATE:
  370. case FILE_MELDATE:
  371. if (file_printf(ms, m->desc, file_fmttime(p->l, 0)) == -1)
  372. return -1;
  373. t = ms->offset + sizeof(time_t);
  374. break;
  375. case FILE_QDATE:
  376. case FILE_BEQDATE:
  377. case FILE_LEQDATE:
  378. if (file_printf(ms, m->desc, file_fmttime((uint32_t)p->q, 1))
  379. == -1)
  380. return -1;
  381. t = ms->offset + sizeof(uint64_t);
  382. break;
  383. case FILE_QLDATE:
  384. case FILE_BEQLDATE:
  385. case FILE_LEQLDATE:
  386. if (file_printf(ms, m->desc, file_fmttime((uint32_t)p->q, 0))
  387. == -1)
  388. return -1;
  389. t = ms->offset + sizeof(uint64_t);
  390. break;
  391. case FILE_REGEX:
  392. if (file_printf(ms, m->desc, p->s) == -1)
  393. return -1;
  394. t = ms->offset + strlen(p->s);
  395. break;
  396. case FILE_SEARCH:
  397. if (file_printf(ms, m->desc, m->value.s) == -1)
  398. return -1;
  399. t = ms->offset + m->vallen;
  400. break;
  401. default:
  402. file_error(ms, 0, "invalid m->type (%d) in mprint()", m->type);
  403. return -1;
  404. }
  405. return(t);
  406. }
  407. #define DO_CVT(fld, cast) \
  408. if (m->mask) \
  409. switch (m->mask_op & 0x7F) { \
  410. case FILE_OPAND: \
  411. p->fld &= cast m->mask; \
  412. break; \
  413. case FILE_OPOR: \
  414. p->fld |= cast m->mask; \
  415. break; \
  416. case FILE_OPXOR: \
  417. p->fld ^= cast m->mask; \
  418. break; \
  419. case FILE_OPADD: \
  420. p->fld += cast m->mask; \
  421. break; \
  422. case FILE_OPMINUS: \
  423. p->fld -= cast m->mask; \
  424. break; \
  425. case FILE_OPMULTIPLY: \
  426. p->fld *= cast m->mask; \
  427. break; \
  428. case FILE_OPDIVIDE: \
  429. p->fld /= cast m->mask; \
  430. break; \
  431. case FILE_OPMODULO: \
  432. p->fld %= cast m->mask; \
  433. break; \
  434. } \
  435. if (m->mask_op & FILE_OPINVERSE) \
  436. p->fld = ~p->fld \
  437. private void
  438. cvt_8(union VALUETYPE *p, const struct magic *m)
  439. {
  440. DO_CVT(b, (uint8_t));
  441. }
  442. private void
  443. cvt_16(union VALUETYPE *p, const struct magic *m)
  444. {
  445. DO_CVT(h, (uint16_t));
  446. }
  447. private void
  448. cvt_32(union VALUETYPE *p, const struct magic *m)
  449. {
  450. DO_CVT(l, (uint32_t));
  451. }
  452. private void
  453. cvt_64(union VALUETYPE *p, const struct magic *m)
  454. {
  455. DO_CVT(q, (uint64_t));
  456. }
  457. /*
  458. * Convert the byte order of the data we are looking at
  459. * While we're here, let's apply the mask operation
  460. * (unless you have a better idea)
  461. */
  462. private int
  463. mconvert(struct magic_set *ms, union VALUETYPE *p, struct magic *m)
  464. {
  465. switch (m->type) {
  466. case FILE_BYTE:
  467. cvt_8(p, m);
  468. return 1;
  469. case FILE_SHORT:
  470. cvt_16(p, m);
  471. return 1;
  472. case FILE_LONG:
  473. case FILE_DATE:
  474. case FILE_LDATE:
  475. cvt_32(p, m);
  476. return 1;
  477. case FILE_QUAD:
  478. case FILE_QDATE:
  479. case FILE_QLDATE:
  480. cvt_64(p, m);
  481. return 1;
  482. case FILE_STRING:
  483. case FILE_BESTRING16:
  484. case FILE_LESTRING16:
  485. {
  486. size_t len;
  487. /* Null terminate and eat *trailing* return */
  488. p->s[sizeof(p->s) - 1] = '\0';
  489. len = strlen(p->s);
  490. if (len-- && p->s[len] == '\n')
  491. p->s[len] = '\0';
  492. return 1;
  493. }
  494. case FILE_PSTRING:
  495. {
  496. char *ptr1 = p->s, *ptr2 = ptr1 + 1;
  497. size_t len = *p->s;
  498. if (len >= sizeof(p->s))
  499. len = sizeof(p->s) - 1;
  500. while (len--)
  501. *ptr1++ = *ptr2++;
  502. *ptr1 = '\0';
  503. len = strlen(p->s);
  504. if (len-- && p->s[len] == '\n')
  505. p->s[len] = '\0';
  506. return 1;
  507. }
  508. case FILE_BESHORT:
  509. p->h = (short)((p->hs[0]<<8)|(p->hs[1]));
  510. cvt_16(p, m);
  511. return 1;
  512. case FILE_BELONG:
  513. case FILE_BEDATE:
  514. case FILE_BELDATE:
  515. p->l = (int32_t)
  516. ((p->hl[0]<<24)|(p->hl[1]<<16)|(p->hl[2]<<8)|(p->hl[3]));
  517. cvt_32(p, m);
  518. return 1;
  519. case FILE_BEQUAD:
  520. case FILE_BEQDATE:
  521. case FILE_BEQLDATE:
  522. p->q = (int64_t)
  523. (((int64_t)p->hq[0]<<56)|((int64_t)p->hq[1]<<48)|
  524. ((int64_t)p->hq[2]<<40)|((int64_t)p->hq[3]<<32)|
  525. (p->hq[4]<<24)|(p->hq[5]<<16)|(p->hq[6]<<8)|(p->hq[7]));
  526. cvt_64(p, m);
  527. return 1;
  528. case FILE_LESHORT:
  529. p->h = (short)((p->hs[1]<<8)|(p->hs[0]));
  530. cvt_16(p, m);
  531. return 1;
  532. case FILE_LELONG:
  533. case FILE_LEDATE:
  534. case FILE_LELDATE:
  535. p->l = (int32_t)
  536. ((p->hl[3]<<24)|(p->hl[2]<<16)|(p->hl[1]<<8)|(p->hl[0]));
  537. cvt_32(p, m);
  538. return 1;
  539. case FILE_LEQUAD:
  540. case FILE_LEQDATE:
  541. case FILE_LEQLDATE:
  542. p->q = (int64_t)
  543. (((int64_t)p->hq[7]<<56)|((int64_t)p->hq[6]<<48)|
  544. ((int64_t)p->hq[5]<<40)|((int64_t)p->hq[4]<<32)|
  545. (p->hq[3]<<24)|(p->hq[2]<<16)|(p->hq[1]<<8)|(p->hq[0]));
  546. cvt_64(p, m);
  547. return 1;
  548. case FILE_MELONG:
  549. case FILE_MEDATE:
  550. case FILE_MELDATE:
  551. p->l = (int32_t)
  552. ((p->hl[1]<<24)|(p->hl[0]<<16)|(p->hl[3]<<8)|(p->hl[2]));
  553. cvt_32(p, m);
  554. return 1;
  555. case FILE_REGEX:
  556. case FILE_SEARCH:
  557. return 1;
  558. default:
  559. file_error(ms, 0, "invalid type %d in mconvert()", m->type);
  560. return 0;
  561. }
  562. }
  563. private void
  564. mdebug(uint32_t offset, const char *str, size_t len)
  565. {
  566. (void) fprintf(stderr, "mget @%d: ", offset);
  567. file_showstr(stderr, str, len);
  568. (void) fputc('\n', stderr);
  569. (void) fputc('\n', stderr);
  570. }
  571. private int
  572. mcopy(struct magic_set *ms, union VALUETYPE *p, int type, int indir,
  573. const unsigned char *s, uint32_t offset, size_t nbytes)
  574. {
  575. if (type == FILE_REGEX && indir == 0) {
  576. /*
  577. * offset is interpreted as last line to search,
  578. * (starting at 1), not as bytes-from start-of-file
  579. */
  580. char *b, *c, *last = NULL;
  581. if (s == NULL) {
  582. p->search.buflen = 0;
  583. p->search.buf = NULL;
  584. return 0;
  585. }
  586. if ((p->search.buf = strdup((const char *)s)) == NULL) {
  587. file_oomem(ms, strlen((const char *)s));
  588. return -1;
  589. }
  590. for (b = p->search.buf; offset &&
  591. ((b = strchr(c = b, '\n')) || (b = strchr(c, '\r')));
  592. offset--, b++) {
  593. last = b;
  594. if (b[0] == '\r' && b[1] == '\n') b++;
  595. }
  596. if (last != NULL)
  597. *last = '\0';
  598. p->search.buflen = last - p->search.buf;
  599. return 0;
  600. }
  601. if (indir == 0 && (type == FILE_BESTRING16 || type == FILE_LESTRING16))
  602. {
  603. const unsigned char *src = s + offset;
  604. const unsigned char *esrc = s + nbytes;
  605. char *dst = p->s, *edst = &p->s[sizeof(p->s) - 1];
  606. if (type == FILE_BESTRING16)
  607. src++;
  608. /* check for pointer overflow */
  609. if (src < s) {
  610. file_error(ms, 0, "invalid offset %zu in mcopy()",
  611. offset);
  612. return -1;
  613. }
  614. for (;src < esrc; src++, dst++) {
  615. if (dst < edst)
  616. *dst = *src++;
  617. else
  618. break;
  619. if (*dst == '\0')
  620. *dst = ' ';
  621. }
  622. *edst = '\0';
  623. return 0;
  624. }
  625. if (offset >= nbytes) {
  626. (void)memset(p, '\0', sizeof(*p));
  627. return 0;
  628. }
  629. if (nbytes - offset < sizeof(*p))
  630. nbytes = nbytes - offset;
  631. else
  632. nbytes = sizeof(*p);
  633. (void)memcpy(p, s + offset, nbytes);
  634. /*
  635. * the usefulness of padding with zeroes eludes me, it
  636. * might even cause problems
  637. */
  638. if (nbytes < sizeof(*p))
  639. (void)memset(((char *)(void *)p) + nbytes, '\0',
  640. sizeof(*p) - nbytes);
  641. return 0;
  642. }
  643. private int
  644. mget(struct magic_set *ms, union VALUETYPE *p, const unsigned char *s,
  645. struct magic *m, size_t nbytes, unsigned int cont_level)
  646. {
  647. uint32_t offset = ms->offset;
  648. if (mcopy(ms, p, m->type, m->flag & INDIR, s, offset, nbytes) == -1)
  649. return -1;
  650. if ((ms->flags & MAGIC_DEBUG) != 0) {
  651. mdebug(offset, (char *)(void *)p, sizeof(union VALUETYPE));
  652. file_mdump(m);
  653. }
  654. if (m->flag & INDIR) {
  655. int off = m->in_offset;
  656. if (m->in_op & FILE_OPINDIRECT) {
  657. const union VALUETYPE *q =
  658. ((const void *)(s + offset + off));
  659. switch (m->in_type) {
  660. case FILE_BYTE:
  661. off = q->b;
  662. break;
  663. case FILE_SHORT:
  664. off = q->h;
  665. break;
  666. case FILE_BESHORT:
  667. off = (short)((q->hs[0]<<8)|(q->hs[1]));
  668. break;
  669. case FILE_LESHORT:
  670. off = (short)((q->hs[1]<<8)|(q->hs[0]));
  671. break;
  672. case FILE_LONG:
  673. off = q->l;
  674. break;
  675. case FILE_BELONG:
  676. off = (int32_t)((q->hl[0]<<24)|(q->hl[1]<<16)|
  677. (q->hl[2]<<8)|(q->hl[3]));
  678. break;
  679. case FILE_LELONG:
  680. off = (int32_t)((q->hl[3]<<24)|(q->hl[2]<<16)|
  681. (q->hl[1]<<8)|(q->hl[0]));
  682. break;
  683. case FILE_MELONG:
  684. off = (int32_t)((q->hl[1]<<24)|(q->hl[0]<<16)|
  685. (q->hl[3]<<8)|(q->hl[2]));
  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_MELONG:
  1005. if (nbytes < (offset + 4))
  1006. return 0;
  1007. if (off) {
  1008. switch (m->in_op & 0x7F) {
  1009. case FILE_OPAND:
  1010. offset = (int32_t)((p->hl[1]<<24)|
  1011. (p->hl[0]<<16)|
  1012. (p->hl[3]<<8)|
  1013. (p->hl[2])) &
  1014. off;
  1015. break;
  1016. case FILE_OPOR:
  1017. offset = (int32_t)((p->hl[1]<<24)|
  1018. (p->hl[0]<<16)|
  1019. (p->hl[3]<<8)|
  1020. (p->hl[2])) |
  1021. off;
  1022. break;
  1023. case FILE_OPXOR:
  1024. offset = (int32_t)((p->hl[1]<<24)|
  1025. (p->hl[0]<<16)|
  1026. (p->hl[3]<<8)|
  1027. (p->hl[2])) ^
  1028. off;
  1029. break;
  1030. case FILE_OPADD:
  1031. offset = (int32_t)((p->hl[1]<<24)|
  1032. (p->hl[0]<<16)|
  1033. (p->hl[3]<<8)|
  1034. (p->hl[2])) +
  1035. off;
  1036. break;
  1037. case FILE_OPMINUS:
  1038. offset = (int32_t)((p->hl[1]<<24)|
  1039. (p->hl[0]<<16)|
  1040. (p->hl[3]<<8)|
  1041. (p->hl[2])) -
  1042. off;
  1043. break;
  1044. case FILE_OPMULTIPLY:
  1045. offset = (int32_t)((p->hl[1]<<24)|
  1046. (p->hl[0]<<16)|
  1047. (p->hl[3]<<8)|
  1048. (p->hl[2])) *
  1049. off;
  1050. break;
  1051. case FILE_OPDIVIDE:
  1052. offset = (int32_t)((p->hl[1]<<24)|
  1053. (p->hl[0]<<16)|
  1054. (p->hl[3]<<8)|
  1055. (p->hl[2])) /
  1056. off;
  1057. break;
  1058. case FILE_OPMODULO:
  1059. offset = (int32_t)((p->hl[1]<<24)|
  1060. (p->hl[0]<<16)|
  1061. (p->hl[3]<<8)|
  1062. (p->hl[2])) %
  1063. off;
  1064. break;
  1065. }
  1066. } else
  1067. offset = (int32_t)((p->hl[1]<<24)|
  1068. (p->hl[0]<<16)|
  1069. (p->hl[3]<<8)|
  1070. (p->hl[2]));
  1071. if (m->in_op & FILE_OPINVERSE)
  1072. offset = ~offset;
  1073. break;
  1074. case FILE_LONG:
  1075. if (nbytes < (offset + 4))
  1076. return 0;
  1077. if (off) {
  1078. switch (m->in_op & 0x7F) {
  1079. case FILE_OPAND:
  1080. offset = p->l & off;
  1081. break;
  1082. case FILE_OPOR:
  1083. offset = p->l | off;
  1084. break;
  1085. case FILE_OPXOR:
  1086. offset = p->l ^ off;
  1087. break;
  1088. case FILE_OPADD:
  1089. offset = p->l + off;
  1090. break;
  1091. case FILE_OPMINUS:
  1092. offset = p->l - off;
  1093. break;
  1094. case FILE_OPMULTIPLY:
  1095. offset = p->l * off;
  1096. break;
  1097. case FILE_OPDIVIDE:
  1098. offset = p->l / off;
  1099. break;
  1100. case FILE_OPMODULO:
  1101. offset = p->l % off;
  1102. break;
  1103. /* case TOOMANYSWITCHBLOCKS:
  1104. * ugh = p->eye % m->strain;
  1105. * rub;
  1106. * case BEER:
  1107. * off = p->tab & m->in_gest;
  1108. * sleep;
  1109. */
  1110. }
  1111. } else
  1112. offset = p->l;
  1113. if (m->in_op & FILE_OPINVERSE)
  1114. offset = ~offset;
  1115. break;
  1116. }
  1117. if (m->flag & INDIROFFADD) offset += ms->c.off[cont_level-1];
  1118. if (mcopy(ms, p, m->type, 0, s, offset, nbytes) == -1)
  1119. return -1;
  1120. ms->offset = offset;
  1121. if ((ms->flags & MAGIC_DEBUG) != 0) {
  1122. mdebug(offset, (char *)(void *)p,
  1123. sizeof(union VALUETYPE));
  1124. file_mdump(m);
  1125. }
  1126. }
  1127. /* Verify we have enough data to match magic type */
  1128. switch (m->type) {
  1129. case FILE_BYTE:
  1130. if (nbytes < (offset + 1)) /* should alway be true */
  1131. return 0;
  1132. break;
  1133. case FILE_SHORT:
  1134. case FILE_BESHORT:
  1135. case FILE_LESHORT:
  1136. if (nbytes < (offset + 2))
  1137. return 0;
  1138. break;
  1139. case FILE_LONG:
  1140. case FILE_BELONG:
  1141. case FILE_LELONG:
  1142. case FILE_MELONG:
  1143. case FILE_DATE:
  1144. case FILE_BEDATE:
  1145. case FILE_LEDATE:
  1146. case FILE_MEDATE:
  1147. case FILE_LDATE:
  1148. case FILE_BELDATE:
  1149. case FILE_LELDATE:
  1150. case FILE_MELDATE:
  1151. if (nbytes < (offset + 4))
  1152. return 0;
  1153. break;
  1154. case FILE_STRING:
  1155. case FILE_PSTRING:
  1156. case FILE_SEARCH:
  1157. if (nbytes < (offset + m->vallen))
  1158. return 0;
  1159. break;
  1160. default: break;
  1161. }
  1162. if (m->type == FILE_SEARCH) {
  1163. size_t mlen = (size_t)(m->mask + m->vallen);
  1164. size_t flen = nbytes - offset;
  1165. if (flen < mlen)
  1166. mlen = flen;
  1167. p->search.buflen = mlen;
  1168. p->search.buf = malloc(mlen + 1);
  1169. if (p->search.buf == NULL) {
  1170. file_error(ms, errno, "Cannot allocate search buffer");
  1171. return 0;
  1172. }
  1173. (void)memcpy(p->search.buf, s + offset, mlen);
  1174. p->search.buf[mlen] = '\0';
  1175. }
  1176. if (!mconvert(ms, p, m))
  1177. return 0;
  1178. return 1;
  1179. }
  1180. private int
  1181. magiccheck(struct magic_set *ms, union VALUETYPE *p, struct magic *m)
  1182. {
  1183. uint64_t l = m->value.q;
  1184. uint64_t v;
  1185. int matched;
  1186. if ( (m->value.s[0] == 'x') && (m->value.s[1] == '\0') ) {
  1187. return 1;
  1188. }
  1189. switch (m->type) {
  1190. case FILE_BYTE:
  1191. v = p->b;
  1192. break;
  1193. case FILE_SHORT:
  1194. case FILE_BESHORT:
  1195. case FILE_LESHORT:
  1196. v = p->h;
  1197. break;
  1198. case FILE_LONG:
  1199. case FILE_BELONG:
  1200. case FILE_LELONG:
  1201. case FILE_MELONG:
  1202. case FILE_DATE:
  1203. case FILE_BEDATE:
  1204. case FILE_LEDATE:
  1205. case FILE_MEDATE:
  1206. case FILE_LDATE:
  1207. case FILE_BELDATE:
  1208. case FILE_LELDATE:
  1209. case FILE_MELDATE:
  1210. v = p->l;
  1211. break;
  1212. case FILE_QUAD:
  1213. case FILE_LEQUAD:
  1214. case FILE_BEQUAD:
  1215. case FILE_QDATE:
  1216. case FILE_BEQDATE:
  1217. case FILE_LEQDATE:
  1218. case FILE_QLDATE:
  1219. case FILE_BEQLDATE:
  1220. case FILE_LEQLDATE:
  1221. v = p->q;
  1222. break;
  1223. case FILE_STRING:
  1224. case FILE_BESTRING16:
  1225. case FILE_LESTRING16:
  1226. case FILE_PSTRING:
  1227. {
  1228. /*
  1229. * What we want here is:
  1230. * v = strncmp(m->value.s, p->s, m->vallen);
  1231. * but ignoring any nulls. bcmp doesn't give -/+/0
  1232. * and isn't universally available anyway.
  1233. */
  1234. unsigned char *a = (unsigned char*)m->value.s;
  1235. unsigned char *b = (unsigned char*)p->s;
  1236. int len = m->vallen;
  1237. l = 0;
  1238. v = 0;
  1239. if (0L == m->mask) { /* normal string: do it fast */
  1240. while (--len >= 0)
  1241. if ((v = *b++ - *a++) != '\0')
  1242. break;
  1243. } else { /* combine the others */
  1244. while (--len >= 0) {
  1245. if ((m->mask & STRING_IGNORE_LOWERCASE) &&
  1246. islower(*a)) {
  1247. if ((v = tolower(*b++) - *a++) != '\0')
  1248. break;
  1249. } else if ((m->mask & STRING_COMPACT_BLANK) &&
  1250. isspace(*a)) {
  1251. a++;
  1252. if (isspace(*b++)) {
  1253. while (isspace(*b))
  1254. b++;
  1255. } else {
  1256. v = 1;
  1257. break;
  1258. }
  1259. } else if (isspace(*a) &&
  1260. (m->mask & STRING_COMPACT_OPTIONAL_BLANK)) {
  1261. a++;
  1262. while (isspace(*b))
  1263. b++;
  1264. } else {
  1265. if ((v = *b++ - *a++) != '\0')
  1266. break;
  1267. }
  1268. }
  1269. }
  1270. break;
  1271. }
  1272. case FILE_REGEX:
  1273. {
  1274. int rc;
  1275. regex_t rx;
  1276. char errmsg[512];
  1277. if (p->search.buf == NULL)
  1278. return 0;
  1279. rc = regcomp(&rx, m->value.s,
  1280. REG_EXTENDED|REG_NOSUB|REG_NEWLINE|
  1281. ((m->mask & STRING_IGNORE_LOWERCASE) ? REG_ICASE : 0));
  1282. if (rc) {
  1283. free(p->search.buf);
  1284. p->search.buf = NULL;
  1285. regerror(rc, &rx, errmsg, sizeof(errmsg));
  1286. file_error(ms, 0, "regex error %d, (%s)", rc, errmsg);
  1287. return -1;
  1288. } else {
  1289. rc = regexec(&rx, p->search.buf, 0, 0, 0);
  1290. regfree(&rx);
  1291. free(p->search.buf);
  1292. p->search.buf = NULL;
  1293. return !rc;
  1294. }
  1295. }
  1296. case FILE_SEARCH:
  1297. {
  1298. /*
  1299. * search for a string in a certain range
  1300. */
  1301. unsigned char *a = (unsigned char*)m->value.s;
  1302. unsigned char *b = (unsigned char*)p->search.buf;
  1303. size_t len, slen = m->vallen;
  1304. size_t range = 0;
  1305. if (slen > sizeof(m->value.s))
  1306. slen = sizeof(m->value.s);
  1307. l = 0;
  1308. v = 0;
  1309. if (b == NULL)
  1310. return 0;
  1311. len = slen;
  1312. while (++range <= m->mask) {
  1313. while (len-- > 0 && (v = *b++ - *a++) == 0)
  1314. continue;
  1315. if (!v) {
  1316. ms->offset += range - 1;
  1317. break;
  1318. }
  1319. if (range + slen >= p->search.buflen) {
  1320. v = 1;
  1321. break;
  1322. }
  1323. len = slen;
  1324. a = (unsigned char*)m->value.s;
  1325. b = (unsigned char*)p->search.buf + range;
  1326. }
  1327. free(p->search.buf);
  1328. p->search.buf = NULL;
  1329. if (v)
  1330. return 0;
  1331. break;
  1332. }
  1333. default:
  1334. file_error(ms, 0, "invalid type %d in magiccheck()", m->type);
  1335. return -1;
  1336. }
  1337. if (m->type != FILE_STRING && m->type != FILE_PSTRING)
  1338. v = file_signextend(ms, m, v);
  1339. switch (m->reln) {
  1340. case 'x':
  1341. if ((ms->flags & MAGIC_DEBUG) != 0)
  1342. (void) fprintf(stderr, "%llu == *any* = 1\n",
  1343. (unsigned long long)v);
  1344. matched = 1;
  1345. break;
  1346. case '!':
  1347. matched = v != l;
  1348. if ((ms->flags & MAGIC_DEBUG) != 0)
  1349. (void) fprintf(stderr, "%llu != %llu = %d\n",
  1350. (unsigned long long)v, (unsigned long long)l,
  1351. matched);
  1352. break;
  1353. case '=':
  1354. matched = v == l;
  1355. if ((ms->flags & MAGIC_DEBUG) != 0)
  1356. (void) fprintf(stderr, "%llu == %llu = %d\n",
  1357. (unsigned long long)v, (unsigned long long)l,
  1358. matched);
  1359. break;
  1360. case '>':
  1361. if (m->flag & UNSIGNED) {
  1362. matched = v > l;
  1363. if ((ms->flags & MAGIC_DEBUG) != 0)
  1364. (void) fprintf(stderr, "%llu > %llu = %d\n",
  1365. (unsigned long long)v,
  1366. (unsigned long long)l, matched);
  1367. }
  1368. else {
  1369. matched = (int32_t) v > (int32_t) l;
  1370. if ((ms->flags & MAGIC_DEBUG) != 0)
  1371. (void) fprintf(stderr, "%lld > %lld = %d\n",
  1372. (long long)v, (long long)l, matched);
  1373. }
  1374. break;
  1375. case '<':
  1376. if (m->flag & UNSIGNED) {
  1377. matched = v < l;
  1378. if ((ms->flags & MAGIC_DEBUG) != 0)
  1379. (void) fprintf(stderr, "%llu < %llu = %d\n",
  1380. (unsigned long long)v,
  1381. (unsigned long long)l, matched);
  1382. }
  1383. else {
  1384. matched = (int32_t) v < (int32_t) l;
  1385. if ((ms->flags & MAGIC_DEBUG) != 0)
  1386. (void) fprintf(stderr, "%lld < %lld = %d\n",
  1387. (long long)v, (long long)l, matched);
  1388. }
  1389. break;
  1390. case '&':
  1391. matched = (v & l) == l;
  1392. if ((ms->flags & MAGIC_DEBUG) != 0)
  1393. (void) fprintf(stderr, "((%llx & %llx) == %llx) = %d\n",
  1394. (unsigned long long)v, (unsigned long long)l,
  1395. (unsigned long long)l, matched);
  1396. break;
  1397. case '^':
  1398. matched = (v & l) != l;
  1399. if ((ms->flags & MAGIC_DEBUG) != 0)
  1400. (void) fprintf(stderr, "((%llx & %llx) != %llx) = %d\n",
  1401. (unsigned long long)v, (unsigned long long)l,
  1402. (unsigned long long)l, matched);
  1403. break;
  1404. default:
  1405. matched = 0;
  1406. file_error(ms, 0, "cannot happen: invalid relation `%c'",
  1407. m->reln);
  1408. return -1;
  1409. }
  1410. return matched;
  1411. }
  1412. private int
  1413. print_sep(struct magic_set *ms, int firstline)
  1414. {
  1415. if (firstline)
  1416. return 0;
  1417. /*
  1418. * we found another match
  1419. * put a newline and '-' to do some simple formatting
  1420. */
  1421. return file_printf(ms, "\n- ");
  1422. }