softmagic.c 44 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007
  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. #ifndef lint
  33. FILE_RCSID("@(#)$File: softmagic.c,v 1.133 2008/11/07 22:50:37 christos Exp $")
  34. #endif /* lint */
  35. #include "magic.h"
  36. #include <string.h>
  37. #include <ctype.h>
  38. #include <stdlib.h>
  39. #include <time.h>
  40. private int match(struct magic_set *, struct magic *, uint32_t,
  41. const unsigned char *, size_t, int);
  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 int32_t moffset(struct magic_set *, 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, size_t);
  50. private int mconvert(struct magic_set *, struct magic *);
  51. private int print_sep(struct magic_set *, int);
  52. private int handle_annotation(struct magic_set *, struct magic *);
  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, int mode)
  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, mode)) != 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, int mode)
  102. {
  103. uint32_t magindex = 0;
  104. unsigned int cont_level = 0;
  105. int need_separator = 0;
  106. int returnval = 0, e; /* if a match is found it is set to 1*/
  107. int firstline = 1; /* a flag to print X\n X\n- X */
  108. int printed_something = 0;
  109. int print = (ms->flags & (MAGIC_MIME|MAGIC_APPLE)) == 0;
  110. if (file_check_mem(ms, cont_level) == -1)
  111. return -1;
  112. for (magindex = 0; magindex < nmagic; magindex++) {
  113. int flush = 0;
  114. struct magic *m = &magic[magindex];
  115. if ((m->flag & BINTEST) != mode) {
  116. /* Skip sub-tests */
  117. while (magic[magindex + 1].cont_level != 0 &&
  118. ++magindex < nmagic)
  119. continue;
  120. continue; /* Skip to next top-level test*/
  121. }
  122. ms->offset = m->offset;
  123. ms->line = m->lineno;
  124. /* if main entry matches, print it... */
  125. switch (mget(ms, s, m, nbytes, cont_level)) {
  126. case -1:
  127. return -1;
  128. case 0:
  129. flush = m->reln != '!';
  130. break;
  131. default:
  132. if (m->type == FILE_INDIRECT)
  133. returnval = 1;
  134. switch (magiccheck(ms, m)) {
  135. case -1:
  136. return -1;
  137. case 0:
  138. flush++;
  139. break;
  140. default:
  141. flush = 0;
  142. break;
  143. }
  144. break;
  145. }
  146. if (flush) {
  147. /*
  148. * main entry didn't match,
  149. * flush its continuations
  150. */
  151. while (magindex < nmagic - 1 &&
  152. magic[magindex + 1].cont_level != 0)
  153. magindex++;
  154. continue;
  155. }
  156. /*
  157. * If we are going to print something, we'll need to print
  158. * a blank before we print something else.
  159. */
  160. if (*m->desc) {
  161. need_separator = 1;
  162. printed_something = 1;
  163. if ((e = handle_annotation(ms, m)) != 0)
  164. return e;
  165. if (print_sep(ms, firstline) == -1)
  166. return -1;
  167. }
  168. if (print && mprint(ms, m) == -1)
  169. return -1;
  170. ms->c.li[cont_level].off = moffset(ms, m);
  171. /* and any continuations that match */
  172. if (file_check_mem(ms, ++cont_level) == -1)
  173. return -1;
  174. while (magic[magindex+1].cont_level != 0 &&
  175. ++magindex < nmagic) {
  176. m = &magic[magindex];
  177. ms->line = m->lineno; /* for messages */
  178. if (cont_level < m->cont_level)
  179. continue;
  180. if (cont_level > m->cont_level) {
  181. /*
  182. * We're at the end of the level
  183. * "cont_level" continuations.
  184. */
  185. cont_level = m->cont_level;
  186. }
  187. ms->offset = m->offset;
  188. if (m->flag & OFFADD) {
  189. ms->offset +=
  190. ms->c.li[cont_level - 1].off;
  191. }
  192. #ifdef ENABLE_CONDITIONALS
  193. if (m->cond == COND_ELSE ||
  194. m->cond == COND_ELIF) {
  195. if (ms->c.li[cont_level].last_match == 1)
  196. continue;
  197. }
  198. #endif
  199. switch (mget(ms, s, m, nbytes, cont_level)) {
  200. case -1:
  201. return -1;
  202. case 0:
  203. if (m->reln != '!')
  204. continue;
  205. flush = 1;
  206. break;
  207. default:
  208. if (m->type == FILE_INDIRECT)
  209. returnval = 1;
  210. flush = 0;
  211. break;
  212. }
  213. switch (flush ? 1 : magiccheck(ms, m)) {
  214. case -1:
  215. return -1;
  216. case 0:
  217. #ifdef ENABLE_CONDITIONALS
  218. ms->c.li[cont_level].last_match = 0;
  219. #endif
  220. break;
  221. default:
  222. #ifdef ENABLE_CONDITIONALS
  223. ms->c.li[cont_level].last_match = 1;
  224. #endif
  225. if (m->type != FILE_DEFAULT)
  226. ms->c.li[cont_level].got_match = 1;
  227. else if (ms->c.li[cont_level].got_match) {
  228. ms->c.li[cont_level].got_match = 0;
  229. break;
  230. }
  231. /*
  232. * If we are going to print something,
  233. * make sure that we have a separator first.
  234. */
  235. if (*m->desc) {
  236. printed_something = 1;
  237. if ((e = handle_annotation(ms, m)) != 0)
  238. return e;
  239. if (print_sep(ms, firstline) == -1)
  240. return -1;
  241. }
  242. /*
  243. * This continuation matched. Print
  244. * its message, with a blank before it
  245. * if the previous item printed and
  246. * this item isn't empty.
  247. */
  248. /* space if previous printed */
  249. if (need_separator
  250. && ((m->flag & NOSPACE) == 0)
  251. && *m->desc) {
  252. if (print &&
  253. file_printf(ms, " ") == -1)
  254. return -1;
  255. need_separator = 0;
  256. }
  257. if (print && mprint(ms, m) == -1)
  258. return -1;
  259. ms->c.li[cont_level].off = moffset(ms, m);
  260. if (*m->desc)
  261. need_separator = 1;
  262. /*
  263. * If we see any continuations
  264. * at a higher level,
  265. * process them.
  266. */
  267. if (file_check_mem(ms, ++cont_level) == -1)
  268. return -1;
  269. break;
  270. }
  271. }
  272. if (printed_something) {
  273. firstline = 0;
  274. if (print)
  275. returnval = 1;
  276. }
  277. if ((ms->flags & MAGIC_CONTINUE) == 0 && printed_something) {
  278. return returnval; /* don't keep searching */
  279. }
  280. }
  281. return returnval; /* This is hit if -k is set or there is no match */
  282. }
  283. private int
  284. check_fmt(struct magic_set *ms, struct magic *m)
  285. {
  286. regex_t rx;
  287. int rc;
  288. if (strchr(m->desc, '%') == NULL)
  289. return 0;
  290. rc = regcomp(&rx, "%[-0-9\\.]*s", REG_EXTENDED|REG_NOSUB);
  291. if (rc) {
  292. char errmsg[512];
  293. (void)regerror(rc, &rx, errmsg, sizeof(errmsg));
  294. file_magerror(ms, "regex error %d, (%s)", rc, errmsg);
  295. return -1;
  296. } else {
  297. rc = regexec(&rx, m->desc, 0, 0, 0);
  298. regfree(&rx);
  299. return !rc;
  300. }
  301. }
  302. #ifndef HAVE_STRNDUP
  303. char * strndup(const char *, size_t);
  304. char *
  305. strndup(const char *str, size_t n)
  306. {
  307. size_t len;
  308. char *copy;
  309. len = strlen(str);
  310. if (len > n)
  311. len = n;
  312. if (!(copy = malloc(len + 1)))
  313. return (NULL);
  314. (void) memcpy(copy, str, len + 1);
  315. copy[len] = '\0';
  316. return (copy);
  317. }
  318. #endif /* HAVE_STRNDUP */
  319. private int32_t
  320. mprint(struct magic_set *ms, struct magic *m)
  321. {
  322. uint64_t v;
  323. float vf;
  324. double vd;
  325. int64_t t = 0;
  326. char buf[128];
  327. union VALUETYPE *p = &ms->ms_value;
  328. switch (m->type) {
  329. case FILE_BYTE:
  330. v = file_signextend(ms, m, (uint64_t)p->b);
  331. switch (check_fmt(ms, m)) {
  332. case -1:
  333. return -1;
  334. case 1:
  335. (void)snprintf(buf, sizeof(buf), "%c",
  336. (unsigned char)v);
  337. if (file_printf(ms, m->desc, buf) == -1)
  338. return -1;
  339. break;
  340. default:
  341. if (file_printf(ms, m->desc, (unsigned char) v) == -1)
  342. return -1;
  343. break;
  344. }
  345. t = ms->offset + sizeof(char);
  346. break;
  347. case FILE_SHORT:
  348. case FILE_BESHORT:
  349. case FILE_LESHORT:
  350. v = file_signextend(ms, m, (uint64_t)p->h);
  351. switch (check_fmt(ms, m)) {
  352. case -1:
  353. return -1;
  354. case 1:
  355. (void)snprintf(buf, sizeof(buf), "%hu",
  356. (unsigned short)v);
  357. if (file_printf(ms, m->desc, buf) == -1)
  358. return -1;
  359. break;
  360. default:
  361. if (
  362. file_printf(ms, m->desc, (unsigned short) v) == -1)
  363. return -1;
  364. break;
  365. }
  366. t = ms->offset + sizeof(short);
  367. break;
  368. case FILE_LONG:
  369. case FILE_BELONG:
  370. case FILE_LELONG:
  371. case FILE_MELONG:
  372. v = file_signextend(ms, m, (uint64_t)p->l);
  373. switch (check_fmt(ms, m)) {
  374. case -1:
  375. return -1;
  376. case 1:
  377. (void)snprintf(buf, sizeof(buf), "%u", (uint32_t)v);
  378. if (file_printf(ms, m->desc, buf) == -1)
  379. return -1;
  380. break;
  381. default:
  382. if (file_printf(ms, m->desc, (uint32_t) v) == -1)
  383. return -1;
  384. break;
  385. }
  386. t = ms->offset + sizeof(int32_t);
  387. break;
  388. case FILE_QUAD:
  389. case FILE_BEQUAD:
  390. case FILE_LEQUAD:
  391. v = file_signextend(ms, m, p->q);
  392. if (file_printf(ms, m->desc, (uint64_t) v) == -1)
  393. return -1;
  394. t = ms->offset + sizeof(int64_t);
  395. break;
  396. case FILE_STRING:
  397. case FILE_PSTRING:
  398. case FILE_BESTRING16:
  399. case FILE_LESTRING16:
  400. if (m->reln == '=' || m->reln == '!') {
  401. if (file_printf(ms, m->desc, m->value.s) == -1)
  402. return -1;
  403. t = ms->offset + m->vallen;
  404. }
  405. else {
  406. if (*m->value.s == '\0')
  407. p->s[strcspn(p->s, "\n")] = '\0';
  408. if (file_printf(ms, m->desc, p->s) == -1)
  409. return -1;
  410. t = ms->offset + strlen(p->s);
  411. if (m->type == FILE_PSTRING)
  412. t++;
  413. }
  414. break;
  415. case FILE_DATE:
  416. case FILE_BEDATE:
  417. case FILE_LEDATE:
  418. case FILE_MEDATE:
  419. if (file_printf(ms, m->desc, file_fmttime(p->l, 1)) == -1)
  420. return -1;
  421. t = ms->offset + sizeof(time_t);
  422. break;
  423. case FILE_LDATE:
  424. case FILE_BELDATE:
  425. case FILE_LELDATE:
  426. case FILE_MELDATE:
  427. if (file_printf(ms, m->desc, file_fmttime(p->l, 0)) == -1)
  428. return -1;
  429. t = ms->offset + sizeof(time_t);
  430. break;
  431. case FILE_QDATE:
  432. case FILE_BEQDATE:
  433. case FILE_LEQDATE:
  434. if (file_printf(ms, m->desc, file_fmttime((uint32_t)p->q,
  435. 1)) == -1)
  436. return -1;
  437. t = ms->offset + sizeof(uint64_t);
  438. break;
  439. case FILE_QLDATE:
  440. case FILE_BEQLDATE:
  441. case FILE_LEQLDATE:
  442. if (file_printf(ms, m->desc, file_fmttime((uint32_t)p->q,
  443. 0)) == -1)
  444. return -1;
  445. t = ms->offset + sizeof(uint64_t);
  446. break;
  447. case FILE_FLOAT:
  448. case FILE_BEFLOAT:
  449. case FILE_LEFLOAT:
  450. vf = p->f;
  451. switch (check_fmt(ms, m)) {
  452. case -1:
  453. return -1;
  454. case 1:
  455. (void)snprintf(buf, sizeof(buf), "%g", vf);
  456. if (file_printf(ms, m->desc, buf) == -1)
  457. return -1;
  458. break;
  459. default:
  460. if (file_printf(ms, m->desc, vf) == -1)
  461. return -1;
  462. break;
  463. }
  464. t = ms->offset + sizeof(float);
  465. break;
  466. case FILE_DOUBLE:
  467. case FILE_BEDOUBLE:
  468. case FILE_LEDOUBLE:
  469. vd = p->d;
  470. switch (check_fmt(ms, m)) {
  471. case -1:
  472. return -1;
  473. case 1:
  474. (void)snprintf(buf, sizeof(buf), "%g", vd);
  475. if (file_printf(ms, m->desc, buf) == -1)
  476. return -1;
  477. break;
  478. default:
  479. if (file_printf(ms, m->desc, vd) == -1)
  480. return -1;
  481. break;
  482. }
  483. t = ms->offset + sizeof(double);
  484. break;
  485. case FILE_REGEX: {
  486. char *cp;
  487. int rval;
  488. cp = strndup((const char *)ms->search.s, ms->search.rm_len);
  489. if (cp == NULL) {
  490. file_oomem(ms, ms->search.rm_len);
  491. return -1;
  492. }
  493. rval = file_printf(ms, m->desc, cp);
  494. free(cp);
  495. if (rval == -1)
  496. return -1;
  497. if ((m->str_flags & REGEX_OFFSET_START))
  498. t = ms->search.offset;
  499. else
  500. t = ms->search.offset + ms->search.rm_len;
  501. break;
  502. }
  503. case FILE_SEARCH:
  504. if (file_printf(ms, m->desc, m->value.s) == -1)
  505. return -1;
  506. if ((m->str_flags & REGEX_OFFSET_START))
  507. t = ms->search.offset;
  508. else
  509. t = ms->search.offset + m->vallen;
  510. break;
  511. case FILE_DEFAULT:
  512. if (file_printf(ms, m->desc, m->value.s) == -1)
  513. return -1;
  514. t = ms->offset;
  515. break;
  516. case FILE_INDIRECT:
  517. t = ms->offset;
  518. break;
  519. default:
  520. file_magerror(ms, "invalid m->type (%d) in mprint()", m->type);
  521. return -1;
  522. }
  523. return (int32_t)t;
  524. }
  525. private int32_t
  526. moffset(struct magic_set *ms, struct magic *m)
  527. {
  528. switch (m->type) {
  529. case FILE_BYTE:
  530. return ms->offset + sizeof(char);
  531. case FILE_SHORT:
  532. case FILE_BESHORT:
  533. case FILE_LESHORT:
  534. return ms->offset + sizeof(short);
  535. case FILE_LONG:
  536. case FILE_BELONG:
  537. case FILE_LELONG:
  538. case FILE_MELONG:
  539. return ms->offset + sizeof(int32_t);
  540. case FILE_QUAD:
  541. case FILE_BEQUAD:
  542. case FILE_LEQUAD:
  543. return ms->offset + sizeof(int64_t);
  544. case FILE_STRING:
  545. case FILE_PSTRING:
  546. case FILE_BESTRING16:
  547. case FILE_LESTRING16:
  548. if (m->reln == '=' || m->reln == '!')
  549. return ms->offset + m->vallen;
  550. else {
  551. union VALUETYPE *p = &ms->ms_value;
  552. uint32_t t;
  553. if (*m->value.s == '\0')
  554. p->s[strcspn(p->s, "\n")] = '\0';
  555. t = ms->offset + strlen(p->s);
  556. if (m->type == FILE_PSTRING)
  557. t++;
  558. return t;
  559. }
  560. case FILE_DATE:
  561. case FILE_BEDATE:
  562. case FILE_LEDATE:
  563. case FILE_MEDATE:
  564. return ms->offset + sizeof(time_t);
  565. case FILE_LDATE:
  566. case FILE_BELDATE:
  567. case FILE_LELDATE:
  568. case FILE_MELDATE:
  569. return ms->offset + sizeof(time_t);
  570. case FILE_QDATE:
  571. case FILE_BEQDATE:
  572. case FILE_LEQDATE:
  573. return ms->offset + sizeof(uint64_t);
  574. case FILE_QLDATE:
  575. case FILE_BEQLDATE:
  576. case FILE_LEQLDATE:
  577. return ms->offset + sizeof(uint64_t);
  578. case FILE_FLOAT:
  579. case FILE_BEFLOAT:
  580. case FILE_LEFLOAT:
  581. return ms->offset + sizeof(float);
  582. case FILE_DOUBLE:
  583. case FILE_BEDOUBLE:
  584. case FILE_LEDOUBLE:
  585. return ms->offset + sizeof(double);
  586. break;
  587. case FILE_REGEX:
  588. if ((m->str_flags & REGEX_OFFSET_START) != 0)
  589. return ms->search.offset;
  590. else
  591. return ms->search.offset + ms->search.rm_len;
  592. case FILE_SEARCH:
  593. if ((m->str_flags & REGEX_OFFSET_START) != 0)
  594. return ms->search.offset;
  595. else
  596. return ms->search.offset + m->vallen;
  597. case FILE_DEFAULT:
  598. return ms->offset;
  599. case FILE_INDIRECT:
  600. return ms->offset;
  601. default:
  602. return 0;
  603. }
  604. }
  605. #define DO_CVT(fld, cast) \
  606. if (m->num_mask) \
  607. switch (m->mask_op & FILE_OPS_MASK) { \
  608. case FILE_OPAND: \
  609. p->fld &= cast m->num_mask; \
  610. break; \
  611. case FILE_OPOR: \
  612. p->fld |= cast m->num_mask; \
  613. break; \
  614. case FILE_OPXOR: \
  615. p->fld ^= cast m->num_mask; \
  616. break; \
  617. case FILE_OPADD: \
  618. p->fld += cast m->num_mask; \
  619. break; \
  620. case FILE_OPMINUS: \
  621. p->fld -= cast m->num_mask; \
  622. break; \
  623. case FILE_OPMULTIPLY: \
  624. p->fld *= cast m->num_mask; \
  625. break; \
  626. case FILE_OPDIVIDE: \
  627. p->fld /= cast m->num_mask; \
  628. break; \
  629. case FILE_OPMODULO: \
  630. p->fld %= cast m->num_mask; \
  631. break; \
  632. } \
  633. if (m->mask_op & FILE_OPINVERSE) \
  634. p->fld = ~p->fld \
  635. private void
  636. cvt_8(union VALUETYPE *p, const struct magic *m)
  637. {
  638. DO_CVT(b, (uint8_t));
  639. }
  640. private void
  641. cvt_16(union VALUETYPE *p, const struct magic *m)
  642. {
  643. DO_CVT(h, (uint16_t));
  644. }
  645. private void
  646. cvt_32(union VALUETYPE *p, const struct magic *m)
  647. {
  648. DO_CVT(l, (uint32_t));
  649. }
  650. private void
  651. cvt_64(union VALUETYPE *p, const struct magic *m)
  652. {
  653. DO_CVT(q, (uint64_t));
  654. }
  655. #define DO_CVT2(fld, cast) \
  656. if (m->num_mask) \
  657. switch (m->mask_op & FILE_OPS_MASK) { \
  658. case FILE_OPADD: \
  659. p->fld += cast m->num_mask; \
  660. break; \
  661. case FILE_OPMINUS: \
  662. p->fld -= cast m->num_mask; \
  663. break; \
  664. case FILE_OPMULTIPLY: \
  665. p->fld *= cast m->num_mask; \
  666. break; \
  667. case FILE_OPDIVIDE: \
  668. p->fld /= cast m->num_mask; \
  669. break; \
  670. } \
  671. private void
  672. cvt_float(union VALUETYPE *p, const struct magic *m)
  673. {
  674. DO_CVT2(f, (float));
  675. }
  676. private void
  677. cvt_double(union VALUETYPE *p, const struct magic *m)
  678. {
  679. DO_CVT2(d, (double));
  680. }
  681. /*
  682. * Convert the byte order of the data we are looking at
  683. * While we're here, let's apply the mask operation
  684. * (unless you have a better idea)
  685. */
  686. private int
  687. mconvert(struct magic_set *ms, struct magic *m)
  688. {
  689. union VALUETYPE *p = &ms->ms_value;
  690. switch (m->type) {
  691. case FILE_BYTE:
  692. cvt_8(p, m);
  693. return 1;
  694. case FILE_SHORT:
  695. cvt_16(p, m);
  696. return 1;
  697. case FILE_LONG:
  698. case FILE_DATE:
  699. case FILE_LDATE:
  700. cvt_32(p, m);
  701. return 1;
  702. case FILE_QUAD:
  703. case FILE_QDATE:
  704. case FILE_QLDATE:
  705. cvt_64(p, m);
  706. return 1;
  707. case FILE_STRING:
  708. case FILE_BESTRING16:
  709. case FILE_LESTRING16: {
  710. /* Null terminate and eat *trailing* return */
  711. p->s[sizeof(p->s) - 1] = '\0';
  712. #if 0
  713. /* Why? breaks magic numbers that end with \xa */
  714. len = strlen(p->s);
  715. if (len-- && p->s[len] == '\n')
  716. p->s[len] = '\0';
  717. #endif
  718. return 1;
  719. }
  720. case FILE_PSTRING: {
  721. char *ptr1 = p->s, *ptr2 = ptr1 + 1;
  722. size_t len = *p->s;
  723. if (len >= sizeof(p->s))
  724. len = sizeof(p->s) - 1;
  725. while (len--)
  726. *ptr1++ = *ptr2++;
  727. *ptr1 = '\0';
  728. #if 0
  729. /* Why? breaks magic numbers that end with \xa */
  730. len = strlen(p->s);
  731. if (len-- && p->s[len] == '\n')
  732. p->s[len] = '\0';
  733. #endif
  734. return 1;
  735. }
  736. case FILE_BESHORT:
  737. p->h = (short)((p->hs[0]<<8)|(p->hs[1]));
  738. cvt_16(p, m);
  739. return 1;
  740. case FILE_BELONG:
  741. case FILE_BEDATE:
  742. case FILE_BELDATE:
  743. p->l = (int32_t)
  744. ((p->hl[0]<<24)|(p->hl[1]<<16)|(p->hl[2]<<8)|(p->hl[3]));
  745. cvt_32(p, m);
  746. return 1;
  747. case FILE_BEQUAD:
  748. case FILE_BEQDATE:
  749. case FILE_BEQLDATE:
  750. p->q = (uint64_t)
  751. (((uint64_t)p->hq[0]<<56)|((uint64_t)p->hq[1]<<48)|
  752. ((uint64_t)p->hq[2]<<40)|((uint64_t)p->hq[3]<<32)|
  753. ((uint64_t)p->hq[4]<<24)|((uint64_t)p->hq[5]<<16)|
  754. ((uint64_t)p->hq[6]<<8)|((uint64_t)p->hq[7]));
  755. cvt_64(p, m);
  756. return 1;
  757. case FILE_LESHORT:
  758. p->h = (short)((p->hs[1]<<8)|(p->hs[0]));
  759. cvt_16(p, m);
  760. return 1;
  761. case FILE_LELONG:
  762. case FILE_LEDATE:
  763. case FILE_LELDATE:
  764. p->l = (int32_t)
  765. ((p->hl[3]<<24)|(p->hl[2]<<16)|(p->hl[1]<<8)|(p->hl[0]));
  766. cvt_32(p, m);
  767. return 1;
  768. case FILE_LEQUAD:
  769. case FILE_LEQDATE:
  770. case FILE_LEQLDATE:
  771. p->q = (uint64_t)
  772. (((uint64_t)p->hq[7]<<56)|((uint64_t)p->hq[6]<<48)|
  773. ((uint64_t)p->hq[5]<<40)|((uint64_t)p->hq[4]<<32)|
  774. ((uint64_t)p->hq[3]<<24)|((uint64_t)p->hq[2]<<16)|
  775. ((uint64_t)p->hq[1]<<8)|((uint64_t)p->hq[0]));
  776. cvt_64(p, m);
  777. return 1;
  778. case FILE_MELONG:
  779. case FILE_MEDATE:
  780. case FILE_MELDATE:
  781. p->l = (int32_t)
  782. ((p->hl[1]<<24)|(p->hl[0]<<16)|(p->hl[3]<<8)|(p->hl[2]));
  783. cvt_32(p, m);
  784. return 1;
  785. case FILE_FLOAT:
  786. cvt_float(p, m);
  787. return 1;
  788. case FILE_BEFLOAT:
  789. p->l = ((uint32_t)p->hl[0]<<24)|((uint32_t)p->hl[1]<<16)|
  790. ((uint32_t)p->hl[2]<<8) |((uint32_t)p->hl[3]);
  791. cvt_float(p, m);
  792. return 1;
  793. case FILE_LEFLOAT:
  794. p->l = ((uint32_t)p->hl[3]<<24)|((uint32_t)p->hl[2]<<16)|
  795. ((uint32_t)p->hl[1]<<8) |((uint32_t)p->hl[0]);
  796. cvt_float(p, m);
  797. return 1;
  798. case FILE_DOUBLE:
  799. cvt_double(p, m);
  800. return 1;
  801. case FILE_BEDOUBLE:
  802. p->q = ((uint64_t)p->hq[0]<<56)|((uint64_t)p->hq[1]<<48)|
  803. ((uint64_t)p->hq[2]<<40)|((uint64_t)p->hq[3]<<32)|
  804. ((uint64_t)p->hq[4]<<24)|((uint64_t)p->hq[5]<<16)|
  805. ((uint64_t)p->hq[6]<<8) |((uint64_t)p->hq[7]);
  806. cvt_double(p, m);
  807. return 1;
  808. case FILE_LEDOUBLE:
  809. p->q = ((uint64_t)p->hq[7]<<56)|((uint64_t)p->hq[6]<<48)|
  810. ((uint64_t)p->hq[5]<<40)|((uint64_t)p->hq[4]<<32)|
  811. ((uint64_t)p->hq[3]<<24)|((uint64_t)p->hq[2]<<16)|
  812. ((uint64_t)p->hq[1]<<8) |((uint64_t)p->hq[0]);
  813. cvt_double(p, m);
  814. return 1;
  815. case FILE_REGEX:
  816. case FILE_SEARCH:
  817. case FILE_DEFAULT:
  818. return 1;
  819. default:
  820. file_magerror(ms, "invalid type %d in mconvert()", m->type);
  821. return 0;
  822. }
  823. }
  824. private void
  825. mdebug(uint32_t offset, const char *str, size_t len)
  826. {
  827. (void) fprintf(stderr, "mget @%d: ", offset);
  828. file_showstr(stderr, str, len);
  829. (void) fputc('\n', stderr);
  830. (void) fputc('\n', stderr);
  831. }
  832. private int
  833. mcopy(struct magic_set *ms, union VALUETYPE *p, int type, int indir,
  834. const unsigned char *s, uint32_t offset, size_t nbytes, size_t linecnt)
  835. {
  836. /*
  837. * Note: FILE_SEARCH and FILE_REGEX do not actually copy
  838. * anything, but setup pointers into the source
  839. */
  840. if (indir == 0) {
  841. switch (type) {
  842. case FILE_SEARCH:
  843. ms->search.s = (const char *)s + offset;
  844. ms->search.s_len = nbytes - offset;
  845. ms->search.offset = offset;
  846. return 0;
  847. case FILE_REGEX: {
  848. const char *b;
  849. const char *c;
  850. const char *last; /* end of search region */
  851. const char *buf; /* start of search region */
  852. const char *end;
  853. size_t lines;
  854. if (s == NULL) {
  855. ms->search.s_len = 0;
  856. ms->search.s = NULL;
  857. return 0;
  858. }
  859. buf = (const char *)s + offset;
  860. end = last = (const char *)s + nbytes;
  861. /* mget() guarantees buf <= last */
  862. for (lines = linecnt, b = buf;
  863. lines && ((b = memchr(c = b, '\n', end - b)) || (b = memchr(c, '\r', end - c)));
  864. lines--, b++) {
  865. last = b;
  866. if (b[0] == '\r' && b[1] == '\n')
  867. b++;
  868. }
  869. if (lines)
  870. last = (const char *)s + nbytes;
  871. ms->search.s = buf;
  872. ms->search.s_len = last - buf;
  873. ms->search.offset = offset;
  874. ms->search.rm_len = 0;
  875. return 0;
  876. }
  877. case FILE_BESTRING16:
  878. case FILE_LESTRING16: {
  879. const unsigned char *src = s + offset;
  880. const unsigned char *esrc = s + nbytes;
  881. char *dst = p->s;
  882. char *edst = &p->s[sizeof(p->s) - 1];
  883. if (type == FILE_BESTRING16)
  884. src++;
  885. /* check for pointer overflow */
  886. if (src < s) {
  887. file_magerror(ms, "invalid offset %u in mcopy()",
  888. offset);
  889. return -1;
  890. }
  891. for (/*EMPTY*/; src < esrc; src += 2, dst++) {
  892. if (dst < edst)
  893. *dst = *src;
  894. else
  895. break;
  896. if (*dst == '\0') {
  897. if (type == FILE_BESTRING16 ?
  898. *(src - 1) != '\0' :
  899. *(src + 1) != '\0')
  900. *dst = ' ';
  901. }
  902. }
  903. *edst = '\0';
  904. return 0;
  905. }
  906. case FILE_STRING: /* XXX - these two should not need */
  907. case FILE_PSTRING: /* to copy anything, but do anyway. */
  908. default:
  909. break;
  910. }
  911. }
  912. if (offset >= nbytes) {
  913. (void)memset(p, '\0', sizeof(*p));
  914. return 0;
  915. }
  916. if (nbytes - offset < sizeof(*p))
  917. nbytes = nbytes - offset;
  918. else
  919. nbytes = sizeof(*p);
  920. (void)memcpy(p, s + offset, nbytes);
  921. /*
  922. * the usefulness of padding with zeroes eludes me, it
  923. * might even cause problems
  924. */
  925. if (nbytes < sizeof(*p))
  926. (void)memset(((char *)(void *)p) + nbytes, '\0',
  927. sizeof(*p) - nbytes);
  928. return 0;
  929. }
  930. private int
  931. mget(struct magic_set *ms, const unsigned char *s,
  932. struct magic *m, size_t nbytes, unsigned int cont_level)
  933. {
  934. uint32_t offset = ms->offset;
  935. uint32_t count = m->str_range;
  936. union VALUETYPE *p = &ms->ms_value;
  937. if (mcopy(ms, p, m->type, m->flag & INDIR, s, offset, nbytes, count) == -1)
  938. return -1;
  939. if ((ms->flags & MAGIC_DEBUG) != 0) {
  940. mdebug(offset, (char *)(void *)p, sizeof(union VALUETYPE));
  941. #ifndef COMPILE_ONLY
  942. file_mdump(m);
  943. #endif
  944. }
  945. if (m->flag & INDIR) {
  946. int off = m->in_offset;
  947. if (m->in_op & FILE_OPINDIRECT) {
  948. const union VALUETYPE *q = CAST(const union VALUETYPE *,
  949. ((const void *)(s + offset + off)));
  950. switch (m->in_type) {
  951. case FILE_BYTE:
  952. off = q->b;
  953. break;
  954. case FILE_SHORT:
  955. off = q->h;
  956. break;
  957. case FILE_BESHORT:
  958. off = (short)((q->hs[0]<<8)|(q->hs[1]));
  959. break;
  960. case FILE_LESHORT:
  961. off = (short)((q->hs[1]<<8)|(q->hs[0]));
  962. break;
  963. case FILE_LONG:
  964. off = q->l;
  965. break;
  966. case FILE_BELONG:
  967. case FILE_BEID3:
  968. off = (int32_t)((q->hl[0]<<24)|(q->hl[1]<<16)|
  969. (q->hl[2]<<8)|(q->hl[3]));
  970. break;
  971. case FILE_LEID3:
  972. case FILE_LELONG:
  973. off = (int32_t)((q->hl[3]<<24)|(q->hl[2]<<16)|
  974. (q->hl[1]<<8)|(q->hl[0]));
  975. break;
  976. case FILE_MELONG:
  977. off = (int32_t)((q->hl[1]<<24)|(q->hl[0]<<16)|
  978. (q->hl[3]<<8)|(q->hl[2]));
  979. break;
  980. }
  981. }
  982. switch (m->in_type) {
  983. case FILE_BYTE:
  984. if (nbytes < (offset + 1))
  985. return 0;
  986. if (off) {
  987. switch (m->in_op & FILE_OPS_MASK) {
  988. case FILE_OPAND:
  989. offset = p->b & off;
  990. break;
  991. case FILE_OPOR:
  992. offset = p->b | off;
  993. break;
  994. case FILE_OPXOR:
  995. offset = p->b ^ off;
  996. break;
  997. case FILE_OPADD:
  998. offset = p->b + off;
  999. break;
  1000. case FILE_OPMINUS:
  1001. offset = p->b - off;
  1002. break;
  1003. case FILE_OPMULTIPLY:
  1004. offset = p->b * off;
  1005. break;
  1006. case FILE_OPDIVIDE:
  1007. offset = p->b / off;
  1008. break;
  1009. case FILE_OPMODULO:
  1010. offset = p->b % off;
  1011. break;
  1012. }
  1013. } else
  1014. offset = p->b;
  1015. if (m->in_op & FILE_OPINVERSE)
  1016. offset = ~offset;
  1017. break;
  1018. case FILE_BESHORT:
  1019. if (nbytes < (offset + 2))
  1020. return 0;
  1021. if (off) {
  1022. switch (m->in_op & FILE_OPS_MASK) {
  1023. case FILE_OPAND:
  1024. offset = (short)((p->hs[0]<<8)|
  1025. (p->hs[1])) &
  1026. off;
  1027. break;
  1028. case FILE_OPOR:
  1029. offset = (short)((p->hs[0]<<8)|
  1030. (p->hs[1])) |
  1031. off;
  1032. break;
  1033. case FILE_OPXOR:
  1034. offset = (short)((p->hs[0]<<8)|
  1035. (p->hs[1])) ^
  1036. off;
  1037. break;
  1038. case FILE_OPADD:
  1039. offset = (short)((p->hs[0]<<8)|
  1040. (p->hs[1])) +
  1041. off;
  1042. break;
  1043. case FILE_OPMINUS:
  1044. offset = (short)((p->hs[0]<<8)|
  1045. (p->hs[1])) -
  1046. off;
  1047. break;
  1048. case FILE_OPMULTIPLY:
  1049. offset = (short)((p->hs[0]<<8)|
  1050. (p->hs[1])) *
  1051. off;
  1052. break;
  1053. case FILE_OPDIVIDE:
  1054. offset = (short)((p->hs[0]<<8)|
  1055. (p->hs[1])) /
  1056. off;
  1057. break;
  1058. case FILE_OPMODULO:
  1059. offset = (short)((p->hs[0]<<8)|
  1060. (p->hs[1])) %
  1061. off;
  1062. break;
  1063. }
  1064. } else
  1065. offset = (short)((p->hs[0]<<8)|
  1066. (p->hs[1]));
  1067. if (m->in_op & FILE_OPINVERSE)
  1068. offset = ~offset;
  1069. break;
  1070. case FILE_LESHORT:
  1071. if (nbytes < (offset + 2))
  1072. return 0;
  1073. if (off) {
  1074. switch (m->in_op & FILE_OPS_MASK) {
  1075. case FILE_OPAND:
  1076. offset = (short)((p->hs[1]<<8)|
  1077. (p->hs[0])) &
  1078. off;
  1079. break;
  1080. case FILE_OPOR:
  1081. offset = (short)((p->hs[1]<<8)|
  1082. (p->hs[0])) |
  1083. off;
  1084. break;
  1085. case FILE_OPXOR:
  1086. offset = (short)((p->hs[1]<<8)|
  1087. (p->hs[0])) ^
  1088. off;
  1089. break;
  1090. case FILE_OPADD:
  1091. offset = (short)((p->hs[1]<<8)|
  1092. (p->hs[0])) +
  1093. off;
  1094. break;
  1095. case FILE_OPMINUS:
  1096. offset = (short)((p->hs[1]<<8)|
  1097. (p->hs[0])) -
  1098. off;
  1099. break;
  1100. case FILE_OPMULTIPLY:
  1101. offset = (short)((p->hs[1]<<8)|
  1102. (p->hs[0])) *
  1103. off;
  1104. break;
  1105. case FILE_OPDIVIDE:
  1106. offset = (short)((p->hs[1]<<8)|
  1107. (p->hs[0])) /
  1108. off;
  1109. break;
  1110. case FILE_OPMODULO:
  1111. offset = (short)((p->hs[1]<<8)|
  1112. (p->hs[0])) %
  1113. off;
  1114. break;
  1115. }
  1116. } else
  1117. offset = (short)((p->hs[1]<<8)|
  1118. (p->hs[0]));
  1119. if (m->in_op & FILE_OPINVERSE)
  1120. offset = ~offset;
  1121. break;
  1122. case FILE_SHORT:
  1123. if (nbytes < (offset + 2))
  1124. return 0;
  1125. if (off) {
  1126. switch (m->in_op & FILE_OPS_MASK) {
  1127. case FILE_OPAND:
  1128. offset = p->h & off;
  1129. break;
  1130. case FILE_OPOR:
  1131. offset = p->h | off;
  1132. break;
  1133. case FILE_OPXOR:
  1134. offset = p->h ^ off;
  1135. break;
  1136. case FILE_OPADD:
  1137. offset = p->h + off;
  1138. break;
  1139. case FILE_OPMINUS:
  1140. offset = p->h - off;
  1141. break;
  1142. case FILE_OPMULTIPLY:
  1143. offset = p->h * off;
  1144. break;
  1145. case FILE_OPDIVIDE:
  1146. offset = p->h / off;
  1147. break;
  1148. case FILE_OPMODULO:
  1149. offset = p->h % off;
  1150. break;
  1151. }
  1152. }
  1153. else
  1154. offset = p->h;
  1155. if (m->in_op & FILE_OPINVERSE)
  1156. offset = ~offset;
  1157. break;
  1158. case FILE_BELONG:
  1159. case FILE_BEID3:
  1160. if (nbytes < (offset + 4))
  1161. return 0;
  1162. if (off) {
  1163. switch (m->in_op & FILE_OPS_MASK) {
  1164. case FILE_OPAND:
  1165. offset = (int32_t)((p->hl[0]<<24)|
  1166. (p->hl[1]<<16)|
  1167. (p->hl[2]<<8)|
  1168. (p->hl[3])) &
  1169. off;
  1170. break;
  1171. case FILE_OPOR:
  1172. offset = (int32_t)((p->hl[0]<<24)|
  1173. (p->hl[1]<<16)|
  1174. (p->hl[2]<<8)|
  1175. (p->hl[3])) |
  1176. off;
  1177. break;
  1178. case FILE_OPXOR:
  1179. offset = (int32_t)((p->hl[0]<<24)|
  1180. (p->hl[1]<<16)|
  1181. (p->hl[2]<<8)|
  1182. (p->hl[3])) ^
  1183. off;
  1184. break;
  1185. case FILE_OPADD:
  1186. offset = (int32_t)((p->hl[0]<<24)|
  1187. (p->hl[1]<<16)|
  1188. (p->hl[2]<<8)|
  1189. (p->hl[3])) +
  1190. off;
  1191. break;
  1192. case FILE_OPMINUS:
  1193. offset = (int32_t)((p->hl[0]<<24)|
  1194. (p->hl[1]<<16)|
  1195. (p->hl[2]<<8)|
  1196. (p->hl[3])) -
  1197. off;
  1198. break;
  1199. case FILE_OPMULTIPLY:
  1200. offset = (int32_t)((p->hl[0]<<24)|
  1201. (p->hl[1]<<16)|
  1202. (p->hl[2]<<8)|
  1203. (p->hl[3])) *
  1204. off;
  1205. break;
  1206. case FILE_OPDIVIDE:
  1207. offset = (int32_t)((p->hl[0]<<24)|
  1208. (p->hl[1]<<16)|
  1209. (p->hl[2]<<8)|
  1210. (p->hl[3])) /
  1211. off;
  1212. break;
  1213. case FILE_OPMODULO:
  1214. offset = (int32_t)((p->hl[0]<<24)|
  1215. (p->hl[1]<<16)|
  1216. (p->hl[2]<<8)|
  1217. (p->hl[3])) %
  1218. off;
  1219. break;
  1220. }
  1221. } else
  1222. offset = (int32_t)((p->hl[0]<<24)|
  1223. (p->hl[1]<<16)|
  1224. (p->hl[2]<<8)|
  1225. (p->hl[3]));
  1226. if (m->in_op & FILE_OPINVERSE)
  1227. offset = ~offset;
  1228. break;
  1229. case FILE_LELONG:
  1230. case FILE_LEID3:
  1231. if (nbytes < (offset + 4))
  1232. return 0;
  1233. if (off) {
  1234. switch (m->in_op & FILE_OPS_MASK) {
  1235. case FILE_OPAND:
  1236. offset = (int32_t)((p->hl[3]<<24)|
  1237. (p->hl[2]<<16)|
  1238. (p->hl[1]<<8)|
  1239. (p->hl[0])) &
  1240. off;
  1241. break;
  1242. case FILE_OPOR:
  1243. offset = (int32_t)((p->hl[3]<<24)|
  1244. (p->hl[2]<<16)|
  1245. (p->hl[1]<<8)|
  1246. (p->hl[0])) |
  1247. off;
  1248. break;
  1249. case FILE_OPXOR:
  1250. offset = (int32_t)((p->hl[3]<<24)|
  1251. (p->hl[2]<<16)|
  1252. (p->hl[1]<<8)|
  1253. (p->hl[0])) ^
  1254. off;
  1255. break;
  1256. case FILE_OPADD:
  1257. offset = (int32_t)((p->hl[3]<<24)|
  1258. (p->hl[2]<<16)|
  1259. (p->hl[1]<<8)|
  1260. (p->hl[0])) +
  1261. off;
  1262. break;
  1263. case FILE_OPMINUS:
  1264. offset = (int32_t)((p->hl[3]<<24)|
  1265. (p->hl[2]<<16)|
  1266. (p->hl[1]<<8)|
  1267. (p->hl[0])) -
  1268. off;
  1269. break;
  1270. case FILE_OPMULTIPLY:
  1271. offset = (int32_t)((p->hl[3]<<24)|
  1272. (p->hl[2]<<16)|
  1273. (p->hl[1]<<8)|
  1274. (p->hl[0])) *
  1275. off;
  1276. break;
  1277. case FILE_OPDIVIDE:
  1278. offset = (int32_t)((p->hl[3]<<24)|
  1279. (p->hl[2]<<16)|
  1280. (p->hl[1]<<8)|
  1281. (p->hl[0])) /
  1282. off;
  1283. break;
  1284. case FILE_OPMODULO:
  1285. offset = (int32_t)((p->hl[3]<<24)|
  1286. (p->hl[2]<<16)|
  1287. (p->hl[1]<<8)|
  1288. (p->hl[0])) %
  1289. off;
  1290. break;
  1291. }
  1292. } else
  1293. offset = (int32_t)((p->hl[3]<<24)|
  1294. (p->hl[2]<<16)|
  1295. (p->hl[1]<<8)|
  1296. (p->hl[0]));
  1297. if (m->in_op & FILE_OPINVERSE)
  1298. offset = ~offset;
  1299. break;
  1300. case FILE_MELONG:
  1301. if (nbytes < (offset + 4))
  1302. return 0;
  1303. if (off) {
  1304. switch (m->in_op & FILE_OPS_MASK) {
  1305. case FILE_OPAND:
  1306. offset = (int32_t)((p->hl[1]<<24)|
  1307. (p->hl[0]<<16)|
  1308. (p->hl[3]<<8)|
  1309. (p->hl[2])) &
  1310. off;
  1311. break;
  1312. case FILE_OPOR:
  1313. offset = (int32_t)((p->hl[1]<<24)|
  1314. (p->hl[0]<<16)|
  1315. (p->hl[3]<<8)|
  1316. (p->hl[2])) |
  1317. off;
  1318. break;
  1319. case FILE_OPXOR:
  1320. offset = (int32_t)((p->hl[1]<<24)|
  1321. (p->hl[0]<<16)|
  1322. (p->hl[3]<<8)|
  1323. (p->hl[2])) ^
  1324. off;
  1325. break;
  1326. case FILE_OPADD:
  1327. offset = (int32_t)((p->hl[1]<<24)|
  1328. (p->hl[0]<<16)|
  1329. (p->hl[3]<<8)|
  1330. (p->hl[2])) +
  1331. off;
  1332. break;
  1333. case FILE_OPMINUS:
  1334. offset = (int32_t)((p->hl[1]<<24)|
  1335. (p->hl[0]<<16)|
  1336. (p->hl[3]<<8)|
  1337. (p->hl[2])) -
  1338. off;
  1339. break;
  1340. case FILE_OPMULTIPLY:
  1341. offset = (int32_t)((p->hl[1]<<24)|
  1342. (p->hl[0]<<16)|
  1343. (p->hl[3]<<8)|
  1344. (p->hl[2])) *
  1345. off;
  1346. break;
  1347. case FILE_OPDIVIDE:
  1348. offset = (int32_t)((p->hl[1]<<24)|
  1349. (p->hl[0]<<16)|
  1350. (p->hl[3]<<8)|
  1351. (p->hl[2])) /
  1352. off;
  1353. break;
  1354. case FILE_OPMODULO:
  1355. offset = (int32_t)((p->hl[1]<<24)|
  1356. (p->hl[0]<<16)|
  1357. (p->hl[3]<<8)|
  1358. (p->hl[2])) %
  1359. off;
  1360. break;
  1361. }
  1362. } else
  1363. offset = (int32_t)((p->hl[1]<<24)|
  1364. (p->hl[0]<<16)|
  1365. (p->hl[3]<<8)|
  1366. (p->hl[2]));
  1367. if (m->in_op & FILE_OPINVERSE)
  1368. offset = ~offset;
  1369. break;
  1370. case FILE_LONG:
  1371. if (nbytes < (offset + 4))
  1372. return 0;
  1373. if (off) {
  1374. switch (m->in_op & FILE_OPS_MASK) {
  1375. case FILE_OPAND:
  1376. offset = p->l & off;
  1377. break;
  1378. case FILE_OPOR:
  1379. offset = p->l | off;
  1380. break;
  1381. case FILE_OPXOR:
  1382. offset = p->l ^ off;
  1383. break;
  1384. case FILE_OPADD:
  1385. offset = p->l + off;
  1386. break;
  1387. case FILE_OPMINUS:
  1388. offset = p->l - off;
  1389. break;
  1390. case FILE_OPMULTIPLY:
  1391. offset = p->l * off;
  1392. break;
  1393. case FILE_OPDIVIDE:
  1394. offset = p->l / off;
  1395. break;
  1396. case FILE_OPMODULO:
  1397. offset = p->l % off;
  1398. break;
  1399. }
  1400. } else
  1401. offset = p->l;
  1402. if (m->in_op & FILE_OPINVERSE)
  1403. offset = ~offset;
  1404. break;
  1405. }
  1406. switch (m->in_type) {
  1407. case FILE_LEID3:
  1408. case FILE_BEID3:
  1409. offset = ((((offset >> 0) & 0x7f) << 0) |
  1410. (((offset >> 8) & 0x7f) << 7) |
  1411. (((offset >> 16) & 0x7f) << 14) |
  1412. (((offset >> 24) & 0x7f) << 21)) + 10;
  1413. break;
  1414. default:
  1415. break;
  1416. }
  1417. if (m->flag & INDIROFFADD) {
  1418. offset += ms->c.li[cont_level-1].off;
  1419. }
  1420. if (mcopy(ms, p, m->type, 0, s, offset, nbytes, count) == -1)
  1421. return -1;
  1422. ms->offset = offset;
  1423. if ((ms->flags & MAGIC_DEBUG) != 0) {
  1424. mdebug(offset, (char *)(void *)p,
  1425. sizeof(union VALUETYPE));
  1426. #ifndef COMPILE_ONLY
  1427. file_mdump(m);
  1428. #endif
  1429. }
  1430. }
  1431. /* Verify we have enough data to match magic type */
  1432. switch (m->type) {
  1433. case FILE_BYTE:
  1434. if (nbytes < (offset + 1)) /* should alway be true */
  1435. return 0;
  1436. break;
  1437. case FILE_SHORT:
  1438. case FILE_BESHORT:
  1439. case FILE_LESHORT:
  1440. if (nbytes < (offset + 2))
  1441. return 0;
  1442. break;
  1443. case FILE_LONG:
  1444. case FILE_BELONG:
  1445. case FILE_LELONG:
  1446. case FILE_MELONG:
  1447. case FILE_DATE:
  1448. case FILE_BEDATE:
  1449. case FILE_LEDATE:
  1450. case FILE_MEDATE:
  1451. case FILE_LDATE:
  1452. case FILE_BELDATE:
  1453. case FILE_LELDATE:
  1454. case FILE_MELDATE:
  1455. case FILE_FLOAT:
  1456. case FILE_BEFLOAT:
  1457. case FILE_LEFLOAT:
  1458. if (nbytes < (offset + 4))
  1459. return 0;
  1460. break;
  1461. case FILE_DOUBLE:
  1462. case FILE_BEDOUBLE:
  1463. case FILE_LEDOUBLE:
  1464. if (nbytes < (offset + 8))
  1465. return 0;
  1466. break;
  1467. case FILE_STRING:
  1468. case FILE_PSTRING:
  1469. case FILE_SEARCH:
  1470. if (nbytes < (offset + m->vallen))
  1471. return 0;
  1472. break;
  1473. case FILE_REGEX:
  1474. if (nbytes < offset)
  1475. return 0;
  1476. break;
  1477. case FILE_INDIRECT:
  1478. if ((ms->flags & (MAGIC_MIME|MAGIC_APPLE)) == 0 &&
  1479. file_printf(ms, m->desc) == -1)
  1480. return -1;
  1481. if (nbytes < offset)
  1482. return 0;
  1483. return file_softmagic(ms, s + offset, nbytes - offset,
  1484. BINTEST);
  1485. case FILE_DEFAULT: /* nothing to check */
  1486. default:
  1487. break;
  1488. }
  1489. if (!mconvert(ms, m))
  1490. return 0;
  1491. return 1;
  1492. }
  1493. private uint64_t
  1494. file_strncmp(const char *s1, const char *s2, size_t len, uint32_t flags)
  1495. {
  1496. /*
  1497. * Convert the source args to unsigned here so that (1) the
  1498. * compare will be unsigned as it is in strncmp() and (2) so
  1499. * the ctype functions will work correctly without extra
  1500. * casting.
  1501. */
  1502. const unsigned char *a = (const unsigned char *)s1;
  1503. const unsigned char *b = (const unsigned char *)s2;
  1504. uint64_t v;
  1505. /*
  1506. * What we want here is v = strncmp(s1, s2, len),
  1507. * but ignoring any nulls.
  1508. */
  1509. v = 0;
  1510. if (0L == flags) { /* normal string: do it fast */
  1511. while (len-- > 0)
  1512. if ((v = *b++ - *a++) != '\0')
  1513. break;
  1514. }
  1515. else { /* combine the others */
  1516. while (len-- > 0) {
  1517. if ((flags & STRING_IGNORE_LOWERCASE) &&
  1518. islower(*a)) {
  1519. if ((v = tolower(*b++) - *a++) != '\0')
  1520. break;
  1521. }
  1522. else if ((flags & STRING_IGNORE_UPPERCASE) &&
  1523. isupper(*a)) {
  1524. if ((v = toupper(*b++) - *a++) != '\0')
  1525. break;
  1526. }
  1527. else if ((flags & STRING_COMPACT_BLANK) &&
  1528. isspace(*a)) {
  1529. a++;
  1530. if (isspace(*b++)) {
  1531. while (isspace(*b))
  1532. b++;
  1533. }
  1534. else {
  1535. v = 1;
  1536. break;
  1537. }
  1538. }
  1539. else if ((flags & STRING_COMPACT_OPTIONAL_BLANK) &&
  1540. isspace(*a)) {
  1541. a++;
  1542. while (isspace(*b))
  1543. b++;
  1544. }
  1545. else {
  1546. if ((v = *b++ - *a++) != '\0')
  1547. break;
  1548. }
  1549. }
  1550. }
  1551. return v;
  1552. }
  1553. private uint64_t
  1554. file_strncmp16(const char *a, const char *b, size_t len, uint32_t flags)
  1555. {
  1556. /*
  1557. * XXX - The 16-bit string compare probably needs to be done
  1558. * differently, especially if the flags are to be supported.
  1559. * At the moment, I am unsure.
  1560. */
  1561. flags = 0;
  1562. return file_strncmp(a, b, len, flags);
  1563. }
  1564. private int
  1565. magiccheck(struct magic_set *ms, struct magic *m)
  1566. {
  1567. uint64_t l = m->value.q;
  1568. uint64_t v;
  1569. float fl, fv;
  1570. double dl, dv;
  1571. int matched;
  1572. union VALUETYPE *p = &ms->ms_value;
  1573. switch (m->type) {
  1574. case FILE_BYTE:
  1575. v = p->b;
  1576. break;
  1577. case FILE_SHORT:
  1578. case FILE_BESHORT:
  1579. case FILE_LESHORT:
  1580. v = p->h;
  1581. break;
  1582. case FILE_LONG:
  1583. case FILE_BELONG:
  1584. case FILE_LELONG:
  1585. case FILE_MELONG:
  1586. case FILE_DATE:
  1587. case FILE_BEDATE:
  1588. case FILE_LEDATE:
  1589. case FILE_MEDATE:
  1590. case FILE_LDATE:
  1591. case FILE_BELDATE:
  1592. case FILE_LELDATE:
  1593. case FILE_MELDATE:
  1594. v = p->l;
  1595. break;
  1596. case FILE_QUAD:
  1597. case FILE_LEQUAD:
  1598. case FILE_BEQUAD:
  1599. case FILE_QDATE:
  1600. case FILE_BEQDATE:
  1601. case FILE_LEQDATE:
  1602. case FILE_QLDATE:
  1603. case FILE_BEQLDATE:
  1604. case FILE_LEQLDATE:
  1605. v = p->q;
  1606. break;
  1607. case FILE_FLOAT:
  1608. case FILE_BEFLOAT:
  1609. case FILE_LEFLOAT:
  1610. fl = m->value.f;
  1611. fv = p->f;
  1612. switch (m->reln) {
  1613. case 'x':
  1614. matched = 1;
  1615. break;
  1616. case '!':
  1617. matched = fv != fl;
  1618. break;
  1619. case '=':
  1620. matched = fv == fl;
  1621. break;
  1622. case '>':
  1623. matched = fv > fl;
  1624. break;
  1625. case '<':
  1626. matched = fv < fl;
  1627. break;
  1628. default:
  1629. matched = 0;
  1630. file_magerror(ms, "cannot happen with float: invalid relation `%c'",
  1631. m->reln);
  1632. return -1;
  1633. }
  1634. return matched;
  1635. case FILE_DOUBLE:
  1636. case FILE_BEDOUBLE:
  1637. case FILE_LEDOUBLE:
  1638. dl = m->value.d;
  1639. dv = p->d;
  1640. switch (m->reln) {
  1641. case 'x':
  1642. matched = 1;
  1643. break;
  1644. case '!':
  1645. matched = dv != dl;
  1646. break;
  1647. case '=':
  1648. matched = dv == dl;
  1649. break;
  1650. case '>':
  1651. matched = dv > dl;
  1652. break;
  1653. case '<':
  1654. matched = dv < dl;
  1655. break;
  1656. default:
  1657. matched = 0;
  1658. file_magerror(ms, "cannot happen with double: invalid relation `%c'", m->reln);
  1659. return -1;
  1660. }
  1661. return matched;
  1662. case FILE_DEFAULT:
  1663. l = 0;
  1664. v = 0;
  1665. break;
  1666. case FILE_STRING:
  1667. case FILE_PSTRING:
  1668. l = 0;
  1669. v = file_strncmp(m->value.s, p->s, (size_t)m->vallen, m->str_flags);
  1670. break;
  1671. case FILE_BESTRING16:
  1672. case FILE_LESTRING16:
  1673. l = 0;
  1674. v = file_strncmp16(m->value.s, p->s, (size_t)m->vallen, m->str_flags);
  1675. break;
  1676. case FILE_SEARCH: { /* search ms->search.s for the string m->value.s */
  1677. size_t slen;
  1678. size_t idx;
  1679. if (ms->search.s == NULL)
  1680. return 0;
  1681. slen = MIN(m->vallen, sizeof(m->value.s));
  1682. l = 0;
  1683. v = 0;
  1684. for (idx = 0; m->str_range == 0 || idx < m->str_range; idx++) {
  1685. if (slen + idx > ms->search.s_len)
  1686. break;
  1687. v = file_strncmp(m->value.s, ms->search.s + idx, slen, m->str_flags);
  1688. if (v == 0) { /* found match */
  1689. ms->search.offset += idx;
  1690. break;
  1691. }
  1692. }
  1693. break;
  1694. }
  1695. case FILE_REGEX: {
  1696. int rc;
  1697. regex_t rx;
  1698. char errmsg[512];
  1699. if (ms->search.s == NULL)
  1700. return 0;
  1701. l = 0;
  1702. rc = regcomp(&rx, m->value.s,
  1703. REG_EXTENDED|REG_NEWLINE|
  1704. ((m->str_flags & STRING_IGNORE_CASE) ? REG_ICASE : 0));
  1705. if (rc) {
  1706. (void)regerror(rc, &rx, errmsg, sizeof(errmsg));
  1707. file_magerror(ms, "regex error %d, (%s)",
  1708. rc, errmsg);
  1709. v = (uint64_t)-1;
  1710. }
  1711. else {
  1712. regmatch_t pmatch[1];
  1713. #ifndef REG_STARTEND
  1714. #define REG_STARTEND 0
  1715. size_t l = ms->search.s_len - 1;
  1716. char c = ms->search.s[l];
  1717. ((char *)(intptr_t)ms->search.s)[l] = '\0';
  1718. #else
  1719. pmatch[0].rm_so = 0;
  1720. pmatch[0].rm_eo = ms->search.s_len;
  1721. #endif
  1722. rc = regexec(&rx, (const char *)ms->search.s,
  1723. 1, pmatch, REG_STARTEND);
  1724. #if REG_STARTEND == 0
  1725. ((char *)(intptr_t)ms->search.s)[l] = c;
  1726. #endif
  1727. switch (rc) {
  1728. case 0:
  1729. ms->search.s += (int)pmatch[0].rm_so;
  1730. ms->search.offset += (size_t)pmatch[0].rm_so;
  1731. ms->search.rm_len =
  1732. (size_t)(pmatch[0].rm_eo - pmatch[0].rm_so);
  1733. v = 0;
  1734. break;
  1735. case REG_NOMATCH:
  1736. v = 1;
  1737. break;
  1738. default:
  1739. (void)regerror(rc, &rx, errmsg, sizeof(errmsg));
  1740. file_magerror(ms, "regexec error %d, (%s)",
  1741. rc, errmsg);
  1742. v = (uint64_t)-1;
  1743. break;
  1744. }
  1745. regfree(&rx);
  1746. }
  1747. if (v == (uint64_t)-1)
  1748. return -1;
  1749. break;
  1750. }
  1751. case FILE_INDIRECT:
  1752. return 1;
  1753. default:
  1754. file_magerror(ms, "invalid type %d in magiccheck()", m->type);
  1755. return -1;
  1756. }
  1757. v = file_signextend(ms, m, v);
  1758. switch (m->reln) {
  1759. case 'x':
  1760. if ((ms->flags & MAGIC_DEBUG) != 0)
  1761. (void) fprintf(stderr, "%llu == *any* = 1\n",
  1762. (unsigned long long)v);
  1763. matched = 1;
  1764. break;
  1765. case '!':
  1766. matched = v != l;
  1767. if ((ms->flags & MAGIC_DEBUG) != 0)
  1768. (void) fprintf(stderr, "%llu != %llu = %d\n",
  1769. (unsigned long long)v, (unsigned long long)l,
  1770. matched);
  1771. break;
  1772. case '=':
  1773. matched = v == l;
  1774. if ((ms->flags & MAGIC_DEBUG) != 0)
  1775. (void) fprintf(stderr, "%llu == %llu = %d\n",
  1776. (unsigned long long)v, (unsigned long long)l,
  1777. matched);
  1778. break;
  1779. case '>':
  1780. if (m->flag & UNSIGNED) {
  1781. matched = v > l;
  1782. if ((ms->flags & MAGIC_DEBUG) != 0)
  1783. (void) fprintf(stderr, "%llu > %llu = %d\n",
  1784. (unsigned long long)v,
  1785. (unsigned long long)l, matched);
  1786. }
  1787. else {
  1788. matched = (int64_t) v > (int64_t) l;
  1789. if ((ms->flags & MAGIC_DEBUG) != 0)
  1790. (void) fprintf(stderr, "%lld > %lld = %d\n",
  1791. (long long)v, (long long)l, matched);
  1792. }
  1793. break;
  1794. case '<':
  1795. if (m->flag & UNSIGNED) {
  1796. matched = v < l;
  1797. if ((ms->flags & MAGIC_DEBUG) != 0)
  1798. (void) fprintf(stderr, "%llu < %llu = %d\n",
  1799. (unsigned long long)v,
  1800. (unsigned long long)l, matched);
  1801. }
  1802. else {
  1803. matched = (int64_t) v < (int64_t) l;
  1804. if ((ms->flags & MAGIC_DEBUG) != 0)
  1805. (void) fprintf(stderr, "%lld < %lld = %d\n",
  1806. (long long)v, (long long)l, matched);
  1807. }
  1808. break;
  1809. case '&':
  1810. matched = (v & l) == l;
  1811. if ((ms->flags & MAGIC_DEBUG) != 0)
  1812. (void) fprintf(stderr, "((%llx & %llx) == %llx) = %d\n",
  1813. (unsigned long long)v, (unsigned long long)l,
  1814. (unsigned long long)l, matched);
  1815. break;
  1816. case '^':
  1817. matched = (v & l) != l;
  1818. if ((ms->flags & MAGIC_DEBUG) != 0)
  1819. (void) fprintf(stderr, "((%llx & %llx) != %llx) = %d\n",
  1820. (unsigned long long)v, (unsigned long long)l,
  1821. (unsigned long long)l, matched);
  1822. break;
  1823. default:
  1824. matched = 0;
  1825. file_magerror(ms, "cannot happen: invalid relation `%c'",
  1826. m->reln);
  1827. return -1;
  1828. }
  1829. return matched;
  1830. }
  1831. private int
  1832. handle_annotation(struct magic_set *ms, struct magic *m)
  1833. {
  1834. if (ms->flags & MAGIC_APPLE) {
  1835. if (file_printf(ms, "%.8s", m->apple) == -1)
  1836. return -1;
  1837. return 1;
  1838. }
  1839. if ((ms->flags & MAGIC_MIME_TYPE) && m->mimetype[0]) {
  1840. if (file_printf(ms, "%s", m->mimetype) == -1)
  1841. return -1;
  1842. return 1;
  1843. }
  1844. return 0;
  1845. }
  1846. private int
  1847. print_sep(struct magic_set *ms, int firstline)
  1848. {
  1849. if (ms->flags & MAGIC_MIME)
  1850. return 0;
  1851. if (firstline)
  1852. return 0;
  1853. /*
  1854. * we found another match
  1855. * put a newline and '-' to do some simple formatting
  1856. */
  1857. return file_printf(ms, "\n- ");
  1858. }