softmagic.c 37 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639
  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. #ifndef lint
  38. FILE_RCSID("@(#)$File: softmagic.c,v 1.99 2007/05/08 14:44:18 christos Exp $")
  39. #endif /* lint */
  40. private int match(struct magic_set *, struct magic *, uint32_t,
  41. const unsigned char *, size_t);
  42. private int mget(struct magic_set *, const unsigned char *,
  43. struct magic *, size_t, unsigned int);
  44. private int magiccheck(struct magic_set *, struct magic *);
  45. private int32_t mprint(struct magic_set *, struct magic *);
  46. private void mdebug(uint32_t, const char *, size_t);
  47. private int mcopy(struct magic_set *, union VALUETYPE *, int, int,
  48. const unsigned char *, uint32_t, size_t, size_t);
  49. private int mconvert(struct magic_set *, struct magic *);
  50. private int print_sep(struct magic_set *, int);
  51. private void cvt_8(union VALUETYPE *, const struct magic *);
  52. private void cvt_16(union VALUETYPE *, const struct magic *);
  53. private void cvt_32(union VALUETYPE *, const struct magic *);
  54. private void cvt_64(union VALUETYPE *, const struct magic *);
  55. /*
  56. * softmagic - lookup one file in parsed, in-memory copy of database
  57. * Passed the name and FILE * of one file to be typed.
  58. */
  59. /*ARGSUSED1*/ /* nbytes passed for regularity, maybe need later */
  60. protected int
  61. file_softmagic(struct magic_set *ms, const unsigned char *buf, size_t nbytes)
  62. {
  63. struct mlist *ml;
  64. int rv;
  65. for (ml = ms->mlist->next; ml != ms->mlist; ml = ml->next)
  66. if ((rv = match(ms, ml->magic, ml->nmagic, buf, nbytes)) != 0)
  67. return rv;
  68. return 0;
  69. }
  70. /*
  71. * Go through the whole list, stopping if you find a match. Process all
  72. * the continuations of that match before returning.
  73. *
  74. * We support multi-level continuations:
  75. *
  76. * At any time when processing a successful top-level match, there is a
  77. * current continuation level; it represents the level of the last
  78. * successfully matched continuation.
  79. *
  80. * Continuations above that level are skipped as, if we see one, it
  81. * means that the continuation that controls them - i.e, the
  82. * lower-level continuation preceding them - failed to match.
  83. *
  84. * Continuations below that level are processed as, if we see one,
  85. * it means we've finished processing or skipping higher-level
  86. * continuations under the control of a successful or unsuccessful
  87. * lower-level continuation, and are now seeing the next lower-level
  88. * continuation and should process it. The current continuation
  89. * level reverts to the level of the one we're seeing.
  90. *
  91. * Continuations at the current level are processed as, if we see
  92. * one, there's no lower-level continuation that may have failed.
  93. *
  94. * If a continuation matches, we bump the current continuation level
  95. * so that higher-level continuations are processed.
  96. */
  97. private int
  98. match(struct magic_set *ms, struct magic *magic, uint32_t nmagic,
  99. const unsigned char *s, size_t nbytes)
  100. {
  101. uint32_t magindex = 0;
  102. unsigned int cont_level = 0;
  103. int need_separator = 0;
  104. int returnval = 0; /* if a match is found it is set to 1*/
  105. int firstline = 1; /* a flag to print X\n X\n- X */
  106. int printed_something = 0;
  107. if (file_check_mem(ms, cont_level) == -1)
  108. return -1;
  109. for (magindex = 0; magindex < nmagic; magindex++) {
  110. int flush;
  111. ms->offset = magic[magindex].offset;
  112. ms->line = magic[magindex].lineno;
  113. /* if main entry matches, print it... */
  114. flush = !mget(ms, s, &magic[magindex], nbytes, cont_level);
  115. if (flush) {
  116. if (magic[magindex].reln == '!')
  117. flush = 0;
  118. } else {
  119. switch (magiccheck(ms, &magic[magindex])) {
  120. case -1:
  121. return -1;
  122. case 0:
  123. flush++;
  124. break;
  125. default:
  126. break;
  127. }
  128. }
  129. if (flush) {
  130. /*
  131. * main entry didn't match,
  132. * flush its continuations
  133. */
  134. while (magindex < nmagic - 1 &&
  135. magic[magindex + 1].cont_level != 0)
  136. magindex++;
  137. continue;
  138. }
  139. /*
  140. * If we are going to print something, we'll need to print
  141. * a blank before we print something else.
  142. */
  143. if (magic[magindex].desc[0]) {
  144. need_separator = 1;
  145. printed_something = 1;
  146. if (print_sep(ms, firstline) == -1)
  147. return -1;
  148. }
  149. if ((ms->c.li[cont_level].off = mprint(ms, &magic[magindex]))
  150. == -1)
  151. return -1;
  152. /* and any continuations that match */
  153. if (file_check_mem(ms, ++cont_level) == -1)
  154. return -1;
  155. while (magic[magindex+1].cont_level != 0 &&
  156. ++magindex < nmagic) {
  157. ms->line = magic[magindex].lineno; /* for messages */
  158. if (cont_level < magic[magindex].cont_level)
  159. continue;
  160. if (cont_level > magic[magindex].cont_level) {
  161. /*
  162. * We're at the end of the level
  163. * "cont_level" continuations.
  164. */
  165. cont_level = magic[magindex].cont_level;
  166. }
  167. ms->offset = magic[magindex].offset;
  168. if (magic[magindex].flag & OFFADD) {
  169. ms->offset +=
  170. ms->c.li[cont_level - 1].off;
  171. }
  172. #ifdef ENABLE_CONDITIONALS
  173. if (magic[magindex].cond == COND_ELSE ||
  174. magic[magindex].cond == COND_ELIF) {
  175. if (ms->c.li[cont_level].last_match == 1)
  176. continue;
  177. }
  178. #endif
  179. flush = !mget(ms, s, &magic[magindex], nbytes,
  180. cont_level);
  181. if (flush && magic[magindex].reln != '!')
  182. continue;
  183. switch (flush ? 1 : magiccheck(ms, &magic[magindex])) {
  184. case -1:
  185. return -1;
  186. case 0:
  187. #ifdef ENABLE_CONDITIONALS
  188. ms->c.li[cont_level].last_match = 0;
  189. #endif
  190. break;
  191. default:
  192. #ifdef ENABLE_CONDITIONALS
  193. ms->c.li[cont_level].last_match = 1;
  194. #endif
  195. if (magic[magindex].type != FILE_DEFAULT)
  196. ms->c.li[cont_level].got_match = 1;
  197. else if (ms->c.li[cont_level].got_match) {
  198. ms->c.li[cont_level].got_match = 0;
  199. break;
  200. }
  201. /*
  202. * If we are going to print something,
  203. * make sure that we have a separator first.
  204. */
  205. if (magic[magindex].desc[0]) {
  206. printed_something = 1;
  207. if (print_sep(ms, firstline) == -1)
  208. return -1;
  209. }
  210. /*
  211. * This continuation matched. Print
  212. * its message, with a blank before it
  213. * if the previous item printed and
  214. * this item isn't empty.
  215. */
  216. /* space if previous printed */
  217. if (need_separator
  218. && (magic[magindex].nospflag == 0)
  219. && (magic[magindex].desc[0] != '\0')) {
  220. if (file_printf(ms, " ") == -1)
  221. return -1;
  222. need_separator = 0;
  223. }
  224. if ((ms->c.li[cont_level].off = mprint(ms, &magic[magindex])) == -1)
  225. return -1;
  226. if (magic[magindex].desc[0])
  227. need_separator = 1;
  228. /*
  229. * If we see any continuations
  230. * at a higher level,
  231. * process them.
  232. */
  233. if (file_check_mem(ms, ++cont_level) == -1)
  234. return -1;
  235. break;
  236. }
  237. }
  238. firstline = 0;
  239. if (printed_something)
  240. returnval = 1;
  241. if ((ms->flags & MAGIC_CONTINUE) == 0 && printed_something) {
  242. return 1; /* don't keep searching */
  243. }
  244. }
  245. return returnval; /* This is hit if -k is set or there is no match */
  246. }
  247. private int
  248. check_fmt(struct magic_set *ms, struct magic *m)
  249. {
  250. regex_t rx;
  251. int rc;
  252. if (strchr(m->desc, '%') == NULL)
  253. return 0;
  254. rc = regcomp(&rx, "%[-0-9\\.]*s", REG_EXTENDED|REG_NOSUB);
  255. if (rc) {
  256. char errmsg[512];
  257. (void)regerror(rc, &rx, errmsg, sizeof(errmsg));
  258. file_magerror(ms, "regex error %d, (%s)", rc, errmsg);
  259. return -1;
  260. } else {
  261. rc = regexec(&rx, m->desc, 0, 0, 0);
  262. regfree(&rx);
  263. return !rc;
  264. }
  265. }
  266. #ifndef HAVE_STRNDUP
  267. char * strndup(const char *, size_t);
  268. char *
  269. strndup(const char *str, size_t n)
  270. {
  271. size_t len;
  272. char *copy;
  273. len = strlen(str);
  274. if (len > n)
  275. len = n;
  276. if (!(copy = malloc(len + 1)))
  277. return (NULL);
  278. (void) memcpy(copy, str, len + 1);
  279. copy[len] = '\0';
  280. return (copy);
  281. }
  282. #endif /* HAVE_STRNDUP */
  283. private int32_t
  284. mprint(struct magic_set *ms, struct magic *m)
  285. {
  286. uint64_t v;
  287. int64_t t = 0;
  288. char buf[512];
  289. union VALUETYPE *p = &ms->ms_value;
  290. switch (m->type) {
  291. case FILE_BYTE:
  292. v = file_signextend(ms, m, (uint64_t)p->b);
  293. switch (check_fmt(ms, m)) {
  294. case -1:
  295. return -1;
  296. case 1:
  297. if (snprintf(buf, sizeof(buf), "%c",
  298. (unsigned char)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 char) v) == -1)
  305. return -1;
  306. break;
  307. }
  308. t = ms->offset + sizeof(char);
  309. break;
  310. case FILE_SHORT:
  311. case FILE_BESHORT:
  312. case FILE_LESHORT:
  313. v = file_signextend(ms, m, (uint64_t)p->h);
  314. switch (check_fmt(ms, m)) {
  315. case -1:
  316. return -1;
  317. case 1:
  318. if (snprintf(buf, sizeof(buf), "%hu",
  319. (unsigned short)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, (unsigned short) v) == -1)
  326. return -1;
  327. break;
  328. }
  329. t = ms->offset + sizeof(short);
  330. break;
  331. case FILE_LONG:
  332. case FILE_BELONG:
  333. case FILE_LELONG:
  334. case FILE_MELONG:
  335. v = file_signextend(ms, m, (uint64_t)p->l);
  336. switch (check_fmt(ms, m)) {
  337. case -1:
  338. return -1;
  339. case 1:
  340. if (snprintf(buf, sizeof(buf), "%u", (uint32_t)v) < 0)
  341. return -1;
  342. if (file_printf(ms, m->desc, buf) == -1)
  343. return -1;
  344. break;
  345. default:
  346. if (file_printf(ms, m->desc, (uint32_t) v) == -1)
  347. return -1;
  348. break;
  349. }
  350. t = ms->offset + sizeof(int32_t);
  351. break;
  352. case FILE_QUAD:
  353. case FILE_BEQUAD:
  354. case FILE_LEQUAD:
  355. v = file_signextend(ms, m, p->q);
  356. if (file_printf(ms, m->desc, (uint64_t) v) == -1)
  357. return -1;
  358. t = ms->offset + sizeof(int64_t);
  359. break;
  360. case FILE_STRING:
  361. case FILE_PSTRING:
  362. case FILE_BESTRING16:
  363. case FILE_LESTRING16:
  364. if (m->reln == '=' || m->reln == '!') {
  365. if (file_printf(ms, m->desc, m->value.s) == -1)
  366. return -1;
  367. t = ms->offset + m->vallen;
  368. }
  369. else {
  370. if (*m->value.s == '\0') {
  371. char *cp = strchr(p->s,'\n');
  372. if (cp)
  373. *cp = '\0';
  374. }
  375. if (file_printf(ms, m->desc, p->s) == -1)
  376. return -1;
  377. t = ms->offset + strlen(p->s);
  378. }
  379. break;
  380. case FILE_DATE:
  381. case FILE_BEDATE:
  382. case FILE_LEDATE:
  383. case FILE_MEDATE:
  384. if (file_printf(ms, m->desc, file_fmttime(p->l, 1)) == -1)
  385. return -1;
  386. t = ms->offset + sizeof(time_t);
  387. break;
  388. case FILE_LDATE:
  389. case FILE_BELDATE:
  390. case FILE_LELDATE:
  391. case FILE_MELDATE:
  392. if (file_printf(ms, m->desc, file_fmttime(p->l, 0)) == -1)
  393. return -1;
  394. t = ms->offset + sizeof(time_t);
  395. break;
  396. case FILE_QDATE:
  397. case FILE_BEQDATE:
  398. case FILE_LEQDATE:
  399. if (file_printf(ms, m->desc, file_fmttime((uint32_t)p->q, 1))
  400. == -1)
  401. return -1;
  402. t = ms->offset + sizeof(uint64_t);
  403. break;
  404. case FILE_QLDATE:
  405. case FILE_BEQLDATE:
  406. case FILE_LEQLDATE:
  407. if (file_printf(ms, m->desc, file_fmttime((uint32_t)p->q, 0))
  408. == -1)
  409. return -1;
  410. t = ms->offset + sizeof(uint64_t);
  411. break;
  412. case FILE_REGEX: {
  413. char *cp;
  414. int rval;
  415. cp = strndup((const char *)ms->search.s, ms->search.rm_len);
  416. if (cp == NULL) {
  417. file_oomem(ms, ms->search.rm_len);
  418. return -1;
  419. }
  420. rval = file_printf(ms, m->desc, cp);
  421. free(cp);
  422. if (rval == -1)
  423. return -1;
  424. if ((m->str_flags & REGEX_OFFSET_START))
  425. t = ms->search.offset;
  426. else
  427. t = ms->search.offset + ms->search.rm_len;
  428. break;
  429. }
  430. case FILE_SEARCH:
  431. if (file_printf(ms, m->desc, m->value.s) == -1)
  432. return -1;
  433. if ((m->str_flags & REGEX_OFFSET_START))
  434. t = ms->search.offset;
  435. else
  436. t = ms->search.offset + m->vallen;
  437. break;
  438. case FILE_DEFAULT:
  439. if (file_printf(ms, m->desc, m->value.s) == -1)
  440. return -1;
  441. t = ms->offset;
  442. break;
  443. default:
  444. file_magerror(ms, "invalid m->type (%d) in mprint()", m->type);
  445. return -1;
  446. }
  447. return(t);
  448. }
  449. #define DO_CVT(fld, cast) \
  450. if (m->num_mask) \
  451. switch (m->mask_op & FILE_OPS_MASK) { \
  452. case FILE_OPAND: \
  453. p->fld &= cast m->num_mask; \
  454. break; \
  455. case FILE_OPOR: \
  456. p->fld |= cast m->num_mask; \
  457. break; \
  458. case FILE_OPXOR: \
  459. p->fld ^= cast m->num_mask; \
  460. break; \
  461. case FILE_OPADD: \
  462. p->fld += cast m->num_mask; \
  463. break; \
  464. case FILE_OPMINUS: \
  465. p->fld -= cast m->num_mask; \
  466. break; \
  467. case FILE_OPMULTIPLY: \
  468. p->fld *= cast m->num_mask; \
  469. break; \
  470. case FILE_OPDIVIDE: \
  471. p->fld /= cast m->num_mask; \
  472. break; \
  473. case FILE_OPMODULO: \
  474. p->fld %= cast m->num_mask; \
  475. break; \
  476. } \
  477. if (m->mask_op & FILE_OPINVERSE) \
  478. p->fld = ~p->fld \
  479. private void
  480. cvt_8(union VALUETYPE *p, const struct magic *m)
  481. {
  482. DO_CVT(b, (uint8_t));
  483. }
  484. private void
  485. cvt_16(union VALUETYPE *p, const struct magic *m)
  486. {
  487. DO_CVT(h, (uint16_t));
  488. }
  489. private void
  490. cvt_32(union VALUETYPE *p, const struct magic *m)
  491. {
  492. DO_CVT(l, (uint32_t));
  493. }
  494. private void
  495. cvt_64(union VALUETYPE *p, const struct magic *m)
  496. {
  497. DO_CVT(q, (uint64_t));
  498. }
  499. /*
  500. * Convert the byte order of the data we are looking at
  501. * While we're here, let's apply the mask operation
  502. * (unless you have a better idea)
  503. */
  504. private int
  505. mconvert(struct magic_set *ms, struct magic *m)
  506. {
  507. union VALUETYPE *p = &ms->ms_value;
  508. switch (m->type) {
  509. case FILE_BYTE:
  510. cvt_8(p, m);
  511. return 1;
  512. case FILE_SHORT:
  513. cvt_16(p, m);
  514. return 1;
  515. case FILE_LONG:
  516. case FILE_DATE:
  517. case FILE_LDATE:
  518. cvt_32(p, m);
  519. return 1;
  520. case FILE_QUAD:
  521. case FILE_QDATE:
  522. case FILE_QLDATE:
  523. cvt_64(p, m);
  524. return 1;
  525. case FILE_STRING:
  526. case FILE_BESTRING16:
  527. case FILE_LESTRING16: {
  528. size_t len;
  529. /* Null terminate and eat *trailing* return */
  530. p->s[sizeof(p->s) - 1] = '\0';
  531. len = strlen(p->s);
  532. if (len-- && p->s[len] == '\n')
  533. p->s[len] = '\0';
  534. return 1;
  535. }
  536. case FILE_PSTRING: {
  537. char *ptr1 = p->s, *ptr2 = ptr1 + 1;
  538. size_t len = *p->s;
  539. if (len >= sizeof(p->s))
  540. len = sizeof(p->s) - 1;
  541. while (len--)
  542. *ptr1++ = *ptr2++;
  543. *ptr1 = '\0';
  544. len = strlen(p->s);
  545. if (len-- && p->s[len] == '\n')
  546. p->s[len] = '\0';
  547. return 1;
  548. }
  549. case FILE_BESHORT:
  550. p->h = (short)((p->hs[0]<<8)|(p->hs[1]));
  551. cvt_16(p, m);
  552. return 1;
  553. case FILE_BELONG:
  554. case FILE_BEDATE:
  555. case FILE_BELDATE:
  556. p->l = (int32_t)
  557. ((p->hl[0]<<24)|(p->hl[1]<<16)|(p->hl[2]<<8)|(p->hl[3]));
  558. cvt_32(p, m);
  559. return 1;
  560. case FILE_BEQUAD:
  561. case FILE_BEQDATE:
  562. case FILE_BEQLDATE:
  563. p->q = (int64_t)
  564. (((int64_t)p->hq[0]<<56)|((int64_t)p->hq[1]<<48)|
  565. ((int64_t)p->hq[2]<<40)|((int64_t)p->hq[3]<<32)|
  566. (p->hq[4]<<24)|(p->hq[5]<<16)|(p->hq[6]<<8)|(p->hq[7]));
  567. cvt_64(p, m);
  568. return 1;
  569. case FILE_LESHORT:
  570. p->h = (short)((p->hs[1]<<8)|(p->hs[0]));
  571. cvt_16(p, m);
  572. return 1;
  573. case FILE_LELONG:
  574. case FILE_LEDATE:
  575. case FILE_LELDATE:
  576. p->l = (int32_t)
  577. ((p->hl[3]<<24)|(p->hl[2]<<16)|(p->hl[1]<<8)|(p->hl[0]));
  578. cvt_32(p, m);
  579. return 1;
  580. case FILE_LEQUAD:
  581. case FILE_LEQDATE:
  582. case FILE_LEQLDATE:
  583. p->q = (int64_t)
  584. (((int64_t)p->hq[7]<<56)|((int64_t)p->hq[6]<<48)|
  585. ((int64_t)p->hq[5]<<40)|((int64_t)p->hq[4]<<32)|
  586. (p->hq[3]<<24)|(p->hq[2]<<16)|(p->hq[1]<<8)|(p->hq[0]));
  587. cvt_64(p, m);
  588. return 1;
  589. case FILE_MELONG:
  590. case FILE_MEDATE:
  591. case FILE_MELDATE:
  592. p->l = (int32_t)
  593. ((p->hl[1]<<24)|(p->hl[0]<<16)|(p->hl[3]<<8)|(p->hl[2]));
  594. cvt_32(p, m);
  595. return 1;
  596. case FILE_REGEX:
  597. case FILE_SEARCH:
  598. case FILE_DEFAULT:
  599. return 1;
  600. default:
  601. file_magerror(ms, "invalid type %d in mconvert()", m->type);
  602. return 0;
  603. }
  604. }
  605. private void
  606. mdebug(uint32_t offset, const char *str, size_t len)
  607. {
  608. (void) fprintf(stderr, "mget @%d: ", offset);
  609. file_showstr(stderr, str, len);
  610. (void) fputc('\n', stderr);
  611. (void) fputc('\n', stderr);
  612. }
  613. private int
  614. mcopy(struct magic_set *ms, union VALUETYPE *p, int type, int indir,
  615. const unsigned char *s, uint32_t offset, size_t nbytes, size_t linecnt)
  616. {
  617. /*
  618. * Note: FILE_SEARCH and FILE_REGEX do not actually copy
  619. * anything, but setup pointers into the source
  620. */
  621. if (indir == 0) {
  622. switch (type) {
  623. case FILE_SEARCH:
  624. ms->search.s = (const char *)s + offset;
  625. ms->search.s_len = nbytes - offset;
  626. return 0;
  627. case FILE_REGEX: {
  628. /*
  629. * offset is interpreted as last line to search,
  630. * (starting at 1), not as bytes-from start-of-file
  631. */
  632. const char *b;
  633. const char *c;
  634. const char *last; /* end of search region */
  635. const char *buf; /* start of search region */
  636. size_t lines;
  637. if (s == NULL) {
  638. ms->search.s_len = 0;
  639. ms->search.s = NULL;
  640. return 0;
  641. }
  642. buf = (const char *)s + offset;
  643. last = (const char *)s + nbytes;
  644. /* mget() guarantees buf <= last */
  645. for (lines = linecnt, b = buf;
  646. lines && ((b = strchr(c = b, '\n')) || (b = strchr(c, '\r')));
  647. lines--, b++) {
  648. last = b;
  649. if (b[0] == '\r' && b[1] == '\n')
  650. b++;
  651. }
  652. if (lines)
  653. last = (const char *)s + nbytes;
  654. ms->search.s = buf;
  655. ms->search.s_len = last - buf;
  656. ms->search.offset = offset;
  657. ms->search.rm_len = 0;
  658. return 0;
  659. }
  660. case FILE_BESTRING16:
  661. case FILE_LESTRING16: {
  662. const unsigned char *src = s + offset;
  663. const unsigned char *esrc = s + nbytes;
  664. char *dst = p->s;
  665. char *edst = &p->s[sizeof(p->s) - 1];
  666. if (type == FILE_BESTRING16)
  667. src++;
  668. /* check for pointer overflow */
  669. if (src < s) {
  670. file_magerror(ms, "invalid offset %zu in mcopy()",
  671. offset);
  672. return -1;
  673. }
  674. for (/*EMPTY*/; src < esrc; src++, dst++) {
  675. if (dst < edst)
  676. *dst = *src++;
  677. else
  678. break;
  679. if (*dst == '\0')
  680. *dst = ' ';
  681. }
  682. *edst = '\0';
  683. return 0;
  684. }
  685. case FILE_STRING: /* XXX - these two should not need */
  686. case FILE_PSTRING: /* to copy anything, but do anyway. */
  687. default:
  688. break;
  689. }
  690. }
  691. if (offset >= nbytes) {
  692. (void)memset(p, '\0', sizeof(*p));
  693. return 0;
  694. }
  695. if (nbytes - offset < sizeof(*p))
  696. nbytes = nbytes - offset;
  697. else
  698. nbytes = sizeof(*p);
  699. (void)memcpy(p, s + offset, nbytes);
  700. /*
  701. * the usefulness of padding with zeroes eludes me, it
  702. * might even cause problems
  703. */
  704. if (nbytes < sizeof(*p))
  705. (void)memset(((char *)(void *)p) + nbytes, '\0',
  706. sizeof(*p) - nbytes);
  707. return 0;
  708. }
  709. private int
  710. mget(struct magic_set *ms, const unsigned char *s,
  711. struct magic *m, size_t nbytes, unsigned int cont_level)
  712. {
  713. uint32_t offset = ms->offset;
  714. uint32_t count = m->str_count;
  715. union VALUETYPE *p = &ms->ms_value;
  716. if (mcopy(ms, p, m->type, m->flag & INDIR, s, offset, nbytes, count) == -1)
  717. return -1;
  718. if ((ms->flags & MAGIC_DEBUG) != 0) {
  719. mdebug(offset, (char *)(void *)p, sizeof(union VALUETYPE));
  720. file_mdump(m);
  721. }
  722. if (m->flag & INDIR) {
  723. int off = m->in_offset;
  724. if (m->in_op & FILE_OPINDIRECT) {
  725. const union VALUETYPE *q =
  726. ((const void *)(s + offset + off));
  727. switch (m->in_type) {
  728. case FILE_BYTE:
  729. off = q->b;
  730. break;
  731. case FILE_SHORT:
  732. off = q->h;
  733. break;
  734. case FILE_BESHORT:
  735. off = (short)((q->hs[0]<<8)|(q->hs[1]));
  736. break;
  737. case FILE_LESHORT:
  738. off = (short)((q->hs[1]<<8)|(q->hs[0]));
  739. break;
  740. case FILE_LONG:
  741. off = q->l;
  742. break;
  743. case FILE_BELONG:
  744. off = (int32_t)((q->hl[0]<<24)|(q->hl[1]<<16)|
  745. (q->hl[2]<<8)|(q->hl[3]));
  746. break;
  747. case FILE_LELONG:
  748. off = (int32_t)((q->hl[3]<<24)|(q->hl[2]<<16)|
  749. (q->hl[1]<<8)|(q->hl[0]));
  750. break;
  751. case FILE_MELONG:
  752. off = (int32_t)((q->hl[1]<<24)|(q->hl[0]<<16)|
  753. (q->hl[3]<<8)|(q->hl[2]));
  754. break;
  755. }
  756. }
  757. switch (m->in_type) {
  758. case FILE_BYTE:
  759. if (nbytes < (offset + 1))
  760. return 0;
  761. if (off) {
  762. switch (m->in_op & FILE_OPS_MASK) {
  763. case FILE_OPAND:
  764. offset = p->b & off;
  765. break;
  766. case FILE_OPOR:
  767. offset = p->b | off;
  768. break;
  769. case FILE_OPXOR:
  770. offset = p->b ^ off;
  771. break;
  772. case FILE_OPADD:
  773. offset = p->b + off;
  774. break;
  775. case FILE_OPMINUS:
  776. offset = p->b - off;
  777. break;
  778. case FILE_OPMULTIPLY:
  779. offset = p->b * off;
  780. break;
  781. case FILE_OPDIVIDE:
  782. offset = p->b / off;
  783. break;
  784. case FILE_OPMODULO:
  785. offset = p->b % off;
  786. break;
  787. }
  788. } else
  789. offset = p->b;
  790. if (m->in_op & FILE_OPINVERSE)
  791. offset = ~offset;
  792. break;
  793. case FILE_BESHORT:
  794. if (nbytes < (offset + 2))
  795. return 0;
  796. if (off) {
  797. switch (m->in_op & FILE_OPS_MASK) {
  798. case FILE_OPAND:
  799. offset = (short)((p->hs[0]<<8)|
  800. (p->hs[1])) &
  801. off;
  802. break;
  803. case FILE_OPOR:
  804. offset = (short)((p->hs[0]<<8)|
  805. (p->hs[1])) |
  806. off;
  807. break;
  808. case FILE_OPXOR:
  809. offset = (short)((p->hs[0]<<8)|
  810. (p->hs[1])) ^
  811. off;
  812. break;
  813. case FILE_OPADD:
  814. offset = (short)((p->hs[0]<<8)|
  815. (p->hs[1])) +
  816. off;
  817. break;
  818. case FILE_OPMINUS:
  819. offset = (short)((p->hs[0]<<8)|
  820. (p->hs[1])) -
  821. off;
  822. break;
  823. case FILE_OPMULTIPLY:
  824. offset = (short)((p->hs[0]<<8)|
  825. (p->hs[1])) *
  826. off;
  827. break;
  828. case FILE_OPDIVIDE:
  829. offset = (short)((p->hs[0]<<8)|
  830. (p->hs[1])) /
  831. off;
  832. break;
  833. case FILE_OPMODULO:
  834. offset = (short)((p->hs[0]<<8)|
  835. (p->hs[1])) %
  836. off;
  837. break;
  838. }
  839. } else
  840. offset = (short)((p->hs[0]<<8)|
  841. (p->hs[1]));
  842. if (m->in_op & FILE_OPINVERSE)
  843. offset = ~offset;
  844. break;
  845. case FILE_LESHORT:
  846. if (nbytes < (offset + 2))
  847. return 0;
  848. if (off) {
  849. switch (m->in_op & FILE_OPS_MASK) {
  850. case FILE_OPAND:
  851. offset = (short)((p->hs[1]<<8)|
  852. (p->hs[0])) &
  853. off;
  854. break;
  855. case FILE_OPOR:
  856. offset = (short)((p->hs[1]<<8)|
  857. (p->hs[0])) |
  858. off;
  859. break;
  860. case FILE_OPXOR:
  861. offset = (short)((p->hs[1]<<8)|
  862. (p->hs[0])) ^
  863. off;
  864. break;
  865. case FILE_OPADD:
  866. offset = (short)((p->hs[1]<<8)|
  867. (p->hs[0])) +
  868. off;
  869. break;
  870. case FILE_OPMINUS:
  871. offset = (short)((p->hs[1]<<8)|
  872. (p->hs[0])) -
  873. off;
  874. break;
  875. case FILE_OPMULTIPLY:
  876. offset = (short)((p->hs[1]<<8)|
  877. (p->hs[0])) *
  878. off;
  879. break;
  880. case FILE_OPDIVIDE:
  881. offset = (short)((p->hs[1]<<8)|
  882. (p->hs[0])) /
  883. off;
  884. break;
  885. case FILE_OPMODULO:
  886. offset = (short)((p->hs[1]<<8)|
  887. (p->hs[0])) %
  888. off;
  889. break;
  890. }
  891. } else
  892. offset = (short)((p->hs[1]<<8)|
  893. (p->hs[0]));
  894. if (m->in_op & FILE_OPINVERSE)
  895. offset = ~offset;
  896. break;
  897. case FILE_SHORT:
  898. if (nbytes < (offset + 2))
  899. return 0;
  900. if (off) {
  901. switch (m->in_op & FILE_OPS_MASK) {
  902. case FILE_OPAND:
  903. offset = p->h & off;
  904. break;
  905. case FILE_OPOR:
  906. offset = p->h | off;
  907. break;
  908. case FILE_OPXOR:
  909. offset = p->h ^ off;
  910. break;
  911. case FILE_OPADD:
  912. offset = p->h + off;
  913. break;
  914. case FILE_OPMINUS:
  915. offset = p->h - off;
  916. break;
  917. case FILE_OPMULTIPLY:
  918. offset = p->h * off;
  919. break;
  920. case FILE_OPDIVIDE:
  921. offset = p->h / off;
  922. break;
  923. case FILE_OPMODULO:
  924. offset = p->h % off;
  925. break;
  926. }
  927. }
  928. else
  929. offset = p->h;
  930. if (m->in_op & FILE_OPINVERSE)
  931. offset = ~offset;
  932. break;
  933. case FILE_BELONG:
  934. if (nbytes < (offset + 4))
  935. return 0;
  936. if (off) {
  937. switch (m->in_op & FILE_OPS_MASK) {
  938. case FILE_OPAND:
  939. offset = (int32_t)((p->hl[0]<<24)|
  940. (p->hl[1]<<16)|
  941. (p->hl[2]<<8)|
  942. (p->hl[3])) &
  943. off;
  944. break;
  945. case FILE_OPOR:
  946. offset = (int32_t)((p->hl[0]<<24)|
  947. (p->hl[1]<<16)|
  948. (p->hl[2]<<8)|
  949. (p->hl[3])) |
  950. off;
  951. break;
  952. case FILE_OPXOR:
  953. offset = (int32_t)((p->hl[0]<<24)|
  954. (p->hl[1]<<16)|
  955. (p->hl[2]<<8)|
  956. (p->hl[3])) ^
  957. off;
  958. break;
  959. case FILE_OPADD:
  960. offset = (int32_t)((p->hl[0]<<24)|
  961. (p->hl[1]<<16)|
  962. (p->hl[2]<<8)|
  963. (p->hl[3])) +
  964. off;
  965. break;
  966. case FILE_OPMINUS:
  967. offset = (int32_t)((p->hl[0]<<24)|
  968. (p->hl[1]<<16)|
  969. (p->hl[2]<<8)|
  970. (p->hl[3])) -
  971. off;
  972. break;
  973. case FILE_OPMULTIPLY:
  974. offset = (int32_t)((p->hl[0]<<24)|
  975. (p->hl[1]<<16)|
  976. (p->hl[2]<<8)|
  977. (p->hl[3])) *
  978. off;
  979. break;
  980. case FILE_OPDIVIDE:
  981. offset = (int32_t)((p->hl[0]<<24)|
  982. (p->hl[1]<<16)|
  983. (p->hl[2]<<8)|
  984. (p->hl[3])) /
  985. off;
  986. break;
  987. case FILE_OPMODULO:
  988. offset = (int32_t)((p->hl[0]<<24)|
  989. (p->hl[1]<<16)|
  990. (p->hl[2]<<8)|
  991. (p->hl[3])) %
  992. off;
  993. break;
  994. }
  995. } else
  996. offset = (int32_t)((p->hl[0]<<24)|
  997. (p->hl[1]<<16)|
  998. (p->hl[2]<<8)|
  999. (p->hl[3]));
  1000. if (m->in_op & FILE_OPINVERSE)
  1001. offset = ~offset;
  1002. break;
  1003. case FILE_LELONG:
  1004. if (nbytes < (offset + 4))
  1005. return 0;
  1006. if (off) {
  1007. switch (m->in_op & FILE_OPS_MASK) {
  1008. case FILE_OPAND:
  1009. offset = (int32_t)((p->hl[3]<<24)|
  1010. (p->hl[2]<<16)|
  1011. (p->hl[1]<<8)|
  1012. (p->hl[0])) &
  1013. off;
  1014. break;
  1015. case FILE_OPOR:
  1016. offset = (int32_t)((p->hl[3]<<24)|
  1017. (p->hl[2]<<16)|
  1018. (p->hl[1]<<8)|
  1019. (p->hl[0])) |
  1020. off;
  1021. break;
  1022. case FILE_OPXOR:
  1023. offset = (int32_t)((p->hl[3]<<24)|
  1024. (p->hl[2]<<16)|
  1025. (p->hl[1]<<8)|
  1026. (p->hl[0])) ^
  1027. off;
  1028. break;
  1029. case FILE_OPADD:
  1030. offset = (int32_t)((p->hl[3]<<24)|
  1031. (p->hl[2]<<16)|
  1032. (p->hl[1]<<8)|
  1033. (p->hl[0])) +
  1034. off;
  1035. break;
  1036. case FILE_OPMINUS:
  1037. offset = (int32_t)((p->hl[3]<<24)|
  1038. (p->hl[2]<<16)|
  1039. (p->hl[1]<<8)|
  1040. (p->hl[0])) -
  1041. off;
  1042. break;
  1043. case FILE_OPMULTIPLY:
  1044. offset = (int32_t)((p->hl[3]<<24)|
  1045. (p->hl[2]<<16)|
  1046. (p->hl[1]<<8)|
  1047. (p->hl[0])) *
  1048. off;
  1049. break;
  1050. case FILE_OPDIVIDE:
  1051. offset = (int32_t)((p->hl[3]<<24)|
  1052. (p->hl[2]<<16)|
  1053. (p->hl[1]<<8)|
  1054. (p->hl[0])) /
  1055. off;
  1056. break;
  1057. case FILE_OPMODULO:
  1058. offset = (int32_t)((p->hl[3]<<24)|
  1059. (p->hl[2]<<16)|
  1060. (p->hl[1]<<8)|
  1061. (p->hl[0])) %
  1062. off;
  1063. break;
  1064. }
  1065. } else
  1066. offset = (int32_t)((p->hl[3]<<24)|
  1067. (p->hl[2]<<16)|
  1068. (p->hl[1]<<8)|
  1069. (p->hl[0]));
  1070. if (m->in_op & FILE_OPINVERSE)
  1071. offset = ~offset;
  1072. break;
  1073. case FILE_MELONG:
  1074. if (nbytes < (offset + 4))
  1075. return 0;
  1076. if (off) {
  1077. switch (m->in_op & FILE_OPS_MASK) {
  1078. case FILE_OPAND:
  1079. offset = (int32_t)((p->hl[1]<<24)|
  1080. (p->hl[0]<<16)|
  1081. (p->hl[3]<<8)|
  1082. (p->hl[2])) &
  1083. off;
  1084. break;
  1085. case FILE_OPOR:
  1086. offset = (int32_t)((p->hl[1]<<24)|
  1087. (p->hl[0]<<16)|
  1088. (p->hl[3]<<8)|
  1089. (p->hl[2])) |
  1090. off;
  1091. break;
  1092. case FILE_OPXOR:
  1093. offset = (int32_t)((p->hl[1]<<24)|
  1094. (p->hl[0]<<16)|
  1095. (p->hl[3]<<8)|
  1096. (p->hl[2])) ^
  1097. off;
  1098. break;
  1099. case FILE_OPADD:
  1100. offset = (int32_t)((p->hl[1]<<24)|
  1101. (p->hl[0]<<16)|
  1102. (p->hl[3]<<8)|
  1103. (p->hl[2])) +
  1104. off;
  1105. break;
  1106. case FILE_OPMINUS:
  1107. offset = (int32_t)((p->hl[1]<<24)|
  1108. (p->hl[0]<<16)|
  1109. (p->hl[3]<<8)|
  1110. (p->hl[2])) -
  1111. off;
  1112. break;
  1113. case FILE_OPMULTIPLY:
  1114. offset = (int32_t)((p->hl[1]<<24)|
  1115. (p->hl[0]<<16)|
  1116. (p->hl[3]<<8)|
  1117. (p->hl[2])) *
  1118. off;
  1119. break;
  1120. case FILE_OPDIVIDE:
  1121. offset = (int32_t)((p->hl[1]<<24)|
  1122. (p->hl[0]<<16)|
  1123. (p->hl[3]<<8)|
  1124. (p->hl[2])) /
  1125. off;
  1126. break;
  1127. case FILE_OPMODULO:
  1128. offset = (int32_t)((p->hl[1]<<24)|
  1129. (p->hl[0]<<16)|
  1130. (p->hl[3]<<8)|
  1131. (p->hl[2])) %
  1132. off;
  1133. break;
  1134. }
  1135. } else
  1136. offset = (int32_t)((p->hl[1]<<24)|
  1137. (p->hl[0]<<16)|
  1138. (p->hl[3]<<8)|
  1139. (p->hl[2]));
  1140. if (m->in_op & FILE_OPINVERSE)
  1141. offset = ~offset;
  1142. break;
  1143. case FILE_LONG:
  1144. if (nbytes < (offset + 4))
  1145. return 0;
  1146. if (off) {
  1147. switch (m->in_op & FILE_OPS_MASK) {
  1148. case FILE_OPAND:
  1149. offset = p->l & off;
  1150. break;
  1151. case FILE_OPOR:
  1152. offset = p->l | off;
  1153. break;
  1154. case FILE_OPXOR:
  1155. offset = p->l ^ off;
  1156. break;
  1157. case FILE_OPADD:
  1158. offset = p->l + off;
  1159. break;
  1160. case FILE_OPMINUS:
  1161. offset = p->l - off;
  1162. break;
  1163. case FILE_OPMULTIPLY:
  1164. offset = p->l * off;
  1165. break;
  1166. case FILE_OPDIVIDE:
  1167. offset = p->l / off;
  1168. break;
  1169. case FILE_OPMODULO:
  1170. offset = p->l % off;
  1171. break;
  1172. /* case TOOMANYSWITCHBLOCKS:
  1173. * ugh = p->eye % m->strain;
  1174. * rub;
  1175. * case BEER:
  1176. * off = p->tab & m->in_gest;
  1177. * sleep;
  1178. */
  1179. }
  1180. } else
  1181. offset = p->l;
  1182. if (m->in_op & FILE_OPINVERSE)
  1183. offset = ~offset;
  1184. break;
  1185. }
  1186. if (m->flag & INDIROFFADD)
  1187. offset += ms->c.li[cont_level-1].off;
  1188. if (mcopy(ms, p, m->type, 0, s, offset, nbytes, count) == -1)
  1189. return -1;
  1190. ms->offset = offset;
  1191. if ((ms->flags & MAGIC_DEBUG) != 0) {
  1192. mdebug(offset, (char *)(void *)p,
  1193. sizeof(union VALUETYPE));
  1194. file_mdump(m);
  1195. }
  1196. }
  1197. /* Verify we have enough data to match magic type */
  1198. switch (m->type) {
  1199. case FILE_BYTE:
  1200. if (nbytes < (offset + 1)) /* should alway be true */
  1201. return 0;
  1202. break;
  1203. case FILE_SHORT:
  1204. case FILE_BESHORT:
  1205. case FILE_LESHORT:
  1206. if (nbytes < (offset + 2))
  1207. return 0;
  1208. break;
  1209. case FILE_LONG:
  1210. case FILE_BELONG:
  1211. case FILE_LELONG:
  1212. case FILE_MELONG:
  1213. case FILE_DATE:
  1214. case FILE_BEDATE:
  1215. case FILE_LEDATE:
  1216. case FILE_MEDATE:
  1217. case FILE_LDATE:
  1218. case FILE_BELDATE:
  1219. case FILE_LELDATE:
  1220. case FILE_MELDATE:
  1221. if (nbytes < (offset + 4))
  1222. return 0;
  1223. break;
  1224. case FILE_STRING:
  1225. case FILE_PSTRING:
  1226. case FILE_SEARCH:
  1227. if (nbytes < (offset + m->vallen))
  1228. return 0;
  1229. break;
  1230. case FILE_REGEX:
  1231. if (nbytes < offset)
  1232. return 0;
  1233. break;
  1234. case FILE_DEFAULT: /* nothing to check */
  1235. default:
  1236. break;
  1237. }
  1238. if (!mconvert(ms, m))
  1239. return 0;
  1240. return 1;
  1241. }
  1242. private uint64_t
  1243. file_strncmp(const char *s1, const char *s2, size_t len, uint32_t flags)
  1244. {
  1245. /*
  1246. * Convert the source args to unsigned here so that (1) the
  1247. * compare will be unsigned as it is in strncmp() and (2) so
  1248. * the ctype functions will work correctly without extra
  1249. * casting.
  1250. */
  1251. const unsigned char *a = (const unsigned char *)s1;
  1252. const unsigned char *b = (const unsigned char *)s2;
  1253. uint64_t v;
  1254. /*
  1255. * What we want here is:
  1256. * v = strncmp(m->value.s, p->s, m->vallen);
  1257. * but ignoring any nulls. bcmp doesn't give -/+/0
  1258. * and isn't universally available anyway.
  1259. */
  1260. v = 0;
  1261. if (0L == flags) { /* normal string: do it fast */
  1262. while (len-- > 0)
  1263. if ((v = *b++ - *a++) != '\0')
  1264. break;
  1265. }
  1266. else { /* combine the others */
  1267. while (len-- > 0) {
  1268. if ((flags & STRING_IGNORE_LOWERCASE) &&
  1269. islower(*a)) {
  1270. if ((v = tolower(*b++) - *a++) != '\0')
  1271. break;
  1272. }
  1273. else if ((flags & STRING_IGNORE_UPPERCASE) &&
  1274. isupper(*a)) {
  1275. if ((v = toupper(*b++) - *a++) != '\0')
  1276. break;
  1277. }
  1278. else if ((flags & STRING_COMPACT_BLANK) &&
  1279. isspace(*a)) {
  1280. a++;
  1281. if (isspace(*b++)) {
  1282. while (isspace(*b))
  1283. b++;
  1284. }
  1285. else {
  1286. v = 1;
  1287. break;
  1288. }
  1289. }
  1290. else if ((flags & STRING_COMPACT_OPTIONAL_BLANK) &&
  1291. isspace(*a)) {
  1292. a++;
  1293. while (isspace(*b))
  1294. b++;
  1295. }
  1296. else {
  1297. if ((v = *b++ - *a++) != '\0')
  1298. break;
  1299. }
  1300. }
  1301. }
  1302. return v;
  1303. }
  1304. private uint64_t
  1305. file_strncmp16(const char *a, const char *b, size_t len, uint32_t flags)
  1306. {
  1307. /*
  1308. * XXX - The 16-bit string compare probably needs to be done
  1309. * differently, especially if the flags are to be supported.
  1310. * At the moment, I am unsure.
  1311. */
  1312. flags = 0;
  1313. return file_strncmp(a, b, len, flags);
  1314. }
  1315. private int
  1316. magiccheck(struct magic_set *ms, struct magic *m)
  1317. {
  1318. uint64_t l = m->value.q;
  1319. uint64_t v;
  1320. int matched;
  1321. union VALUETYPE *p = &ms->ms_value;
  1322. switch (m->type) {
  1323. case FILE_BYTE:
  1324. v = p->b;
  1325. break;
  1326. case FILE_SHORT:
  1327. case FILE_BESHORT:
  1328. case FILE_LESHORT:
  1329. v = p->h;
  1330. break;
  1331. case FILE_LONG:
  1332. case FILE_BELONG:
  1333. case FILE_LELONG:
  1334. case FILE_MELONG:
  1335. case FILE_DATE:
  1336. case FILE_BEDATE:
  1337. case FILE_LEDATE:
  1338. case FILE_MEDATE:
  1339. case FILE_LDATE:
  1340. case FILE_BELDATE:
  1341. case FILE_LELDATE:
  1342. case FILE_MELDATE:
  1343. v = p->l;
  1344. break;
  1345. case FILE_QUAD:
  1346. case FILE_LEQUAD:
  1347. case FILE_BEQUAD:
  1348. case FILE_QDATE:
  1349. case FILE_BEQDATE:
  1350. case FILE_LEQDATE:
  1351. case FILE_QLDATE:
  1352. case FILE_BEQLDATE:
  1353. case FILE_LEQLDATE:
  1354. v = p->q;
  1355. break;
  1356. case FILE_DEFAULT:
  1357. l = 0;
  1358. v = 0;
  1359. break;
  1360. case FILE_STRING:
  1361. case FILE_PSTRING:
  1362. l = 0;
  1363. v = file_strncmp(m->value.s, p->s, (size_t)m->vallen, m->str_flags);
  1364. break;
  1365. case FILE_BESTRING16:
  1366. case FILE_LESTRING16:
  1367. l = 0;
  1368. v = file_strncmp16(m->value.s, p->s, (size_t)m->vallen, m->str_flags);
  1369. break;
  1370. case FILE_SEARCH: { /* search ms->search.s for the string m->value.s */
  1371. size_t slen;
  1372. size_t idx;
  1373. if (ms->search.s == NULL)
  1374. return 0;
  1375. slen = MIN(m->vallen, sizeof(m->value.s));
  1376. l = 0;
  1377. v = 0;
  1378. ms->search.offset = m->offset;
  1379. for (idx = 0; m->str_count == 0 || idx < m->str_count; idx++) {
  1380. if (slen + idx > ms->search.s_len)
  1381. break;
  1382. v = file_strncmp(m->value.s, ms->search.s + idx, slen, m->str_flags);
  1383. if (v == 0) { /* found match */
  1384. ms->search.offset = m->offset + idx;
  1385. break;
  1386. }
  1387. }
  1388. break;
  1389. }
  1390. case FILE_REGEX: {
  1391. int rc;
  1392. regex_t rx;
  1393. char errmsg[512];
  1394. if (ms->search.s == NULL)
  1395. return 0;
  1396. l = 0;
  1397. rc = regcomp(&rx, m->value.s,
  1398. REG_EXTENDED|REG_NEWLINE|
  1399. ((m->str_flags & STRING_IGNORE_CASE) ? REG_ICASE : 0));
  1400. if (rc) {
  1401. (void)regerror(rc, &rx, errmsg, sizeof(errmsg));
  1402. file_magerror(ms, "regex error %d, (%s)",
  1403. rc, errmsg);
  1404. v = (uint64_t)-1;
  1405. }
  1406. else {
  1407. regmatch_t pmatch[1];
  1408. #ifndef REG_STARTEND
  1409. #define REG_STARTEND 0
  1410. size_t l = ms->search.s_len - 1;
  1411. char c = ms->search.s[l];
  1412. ((char *)(intptr_t)ms->search.s)[l] = '\0';
  1413. #else
  1414. pmatch[0].rm_so = 0;
  1415. pmatch[0].rm_eo = ms->search.s_len;
  1416. #endif
  1417. rc = regexec(&rx, (const char *)ms->search.s,
  1418. 1, pmatch, REG_STARTEND);
  1419. #if REG_STARTEND == 0
  1420. ((char *)(intptr_t)ms->search.s)[l] = c;
  1421. #endif
  1422. switch (rc) {
  1423. case 0:
  1424. ms->search.s += (int)pmatch[0].rm_so;
  1425. ms->search.offset += (size_t)pmatch[0].rm_so;
  1426. ms->search.rm_len =
  1427. (size_t)(pmatch[0].rm_eo - pmatch[0].rm_so);
  1428. v = 0;
  1429. break;
  1430. case REG_NOMATCH:
  1431. v = 1;
  1432. break;
  1433. default:
  1434. (void)regerror(rc, &rx, errmsg, sizeof(errmsg));
  1435. file_magerror(ms, "regexec error %d, (%s)",
  1436. rc, errmsg);
  1437. v = (uint64_t)-1;
  1438. break;
  1439. }
  1440. regfree(&rx);
  1441. }
  1442. if (v == (uint64_t)-1)
  1443. return -1;
  1444. break;
  1445. }
  1446. default:
  1447. file_magerror(ms, "invalid type %d in magiccheck()", m->type);
  1448. return -1;
  1449. }
  1450. v = file_signextend(ms, m, v);
  1451. switch (m->reln) {
  1452. case 'x':
  1453. if ((ms->flags & MAGIC_DEBUG) != 0)
  1454. (void) fprintf(stderr, "%llu == *any* = 1\n",
  1455. (unsigned long long)v);
  1456. matched = 1;
  1457. break;
  1458. case '!':
  1459. matched = v != l;
  1460. if ((ms->flags & MAGIC_DEBUG) != 0)
  1461. (void) fprintf(stderr, "%llu != %llu = %d\n",
  1462. (unsigned long long)v, (unsigned long long)l,
  1463. matched);
  1464. break;
  1465. case '=':
  1466. matched = v == l;
  1467. if ((ms->flags & MAGIC_DEBUG) != 0)
  1468. (void) fprintf(stderr, "%llu == %llu = %d\n",
  1469. (unsigned long long)v, (unsigned long long)l,
  1470. matched);
  1471. break;
  1472. case '>':
  1473. if (m->flag & UNSIGNED) {
  1474. matched = v > l;
  1475. if ((ms->flags & MAGIC_DEBUG) != 0)
  1476. (void) fprintf(stderr, "%llu > %llu = %d\n",
  1477. (unsigned long long)v,
  1478. (unsigned long long)l, matched);
  1479. }
  1480. else {
  1481. matched = (int64_t) v > (int64_t) l;
  1482. if ((ms->flags & MAGIC_DEBUG) != 0)
  1483. (void) fprintf(stderr, "%lld > %lld = %d\n",
  1484. (long long)v, (long long)l, matched);
  1485. }
  1486. break;
  1487. case '<':
  1488. if (m->flag & UNSIGNED) {
  1489. matched = v < l;
  1490. if ((ms->flags & MAGIC_DEBUG) != 0)
  1491. (void) fprintf(stderr, "%llu < %llu = %d\n",
  1492. (unsigned long long)v,
  1493. (unsigned long long)l, matched);
  1494. }
  1495. else {
  1496. matched = (int64_t) v < (int64_t) l;
  1497. if ((ms->flags & MAGIC_DEBUG) != 0)
  1498. (void) fprintf(stderr, "%lld < %lld = %d\n",
  1499. (long long)v, (long long)l, matched);
  1500. }
  1501. break;
  1502. case '&':
  1503. matched = (v & l) == l;
  1504. if ((ms->flags & MAGIC_DEBUG) != 0)
  1505. (void) fprintf(stderr, "((%llx & %llx) == %llx) = %d\n",
  1506. (unsigned long long)v, (unsigned long long)l,
  1507. (unsigned long long)l, matched);
  1508. break;
  1509. case '^':
  1510. matched = (v & l) != l;
  1511. if ((ms->flags & MAGIC_DEBUG) != 0)
  1512. (void) fprintf(stderr, "((%llx & %llx) != %llx) = %d\n",
  1513. (unsigned long long)v, (unsigned long long)l,
  1514. (unsigned long long)l, matched);
  1515. break;
  1516. default:
  1517. matched = 0;
  1518. file_magerror(ms, "cannot happen: invalid relation `%c'",
  1519. m->reln);
  1520. return -1;
  1521. }
  1522. return matched;
  1523. }
  1524. private int
  1525. print_sep(struct magic_set *ms, int firstline)
  1526. {
  1527. if (firstline)
  1528. return 0;
  1529. /*
  1530. * we found another match
  1531. * put a newline and '-' to do some simple formatting
  1532. */
  1533. return file_printf(ms, "\n- ");
  1534. }