softmagic.c 28 KB

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