xer_decoder.c 8.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369
  1. /*
  2. * Copyright (c) 2004-2017 Lev Walkin <vlm@lionet.info>. All rights reserved.
  3. * Redistribution and modifications are permitted subject to BSD license.
  4. */
  5. #include <asn_application.h>
  6. #include <asn_internal.h>
  7. #include <xer_support.h> /* XER/XML parsing support */
  8. /*
  9. * Decode the XER encoding of a given type.
  10. */
  11. asn_dec_rval_t
  12. xer_decode(const asn_codec_ctx_t *opt_codec_ctx,
  13. const asn_TYPE_descriptor_t *td, void **struct_ptr,
  14. const void *buffer, size_t size) {
  15. asn_codec_ctx_t s_codec_ctx;
  16. /*
  17. * Stack checker requires that the codec context
  18. * must be allocated on the stack.
  19. */
  20. if(opt_codec_ctx) {
  21. if(opt_codec_ctx->max_stack_size) {
  22. s_codec_ctx = *opt_codec_ctx;
  23. opt_codec_ctx = &s_codec_ctx;
  24. }
  25. } else {
  26. /* If context is not given, be security-conscious anyway */
  27. memset(&s_codec_ctx, 0, sizeof(s_codec_ctx));
  28. s_codec_ctx.max_stack_size = ASN__DEFAULT_STACK_MAX;
  29. opt_codec_ctx = &s_codec_ctx;
  30. }
  31. /*
  32. * Invoke type-specific decoder.
  33. */
  34. return td->op->xer_decoder(opt_codec_ctx, td, struct_ptr, 0, buffer, size);
  35. }
  36. struct xer__cb_arg {
  37. pxml_chunk_type_e chunk_type;
  38. size_t chunk_size;
  39. const void *chunk_buf;
  40. int callback_not_invoked;
  41. };
  42. static int
  43. xer__token_cb(pxml_chunk_type_e type, const void *_chunk_data, size_t _chunk_size, void *key) {
  44. struct xer__cb_arg *arg = (struct xer__cb_arg *)key;
  45. arg->chunk_type = type;
  46. arg->chunk_size = _chunk_size;
  47. arg->chunk_buf = _chunk_data;
  48. arg->callback_not_invoked = 0;
  49. return -1; /* Terminate the XML parsing */
  50. }
  51. /*
  52. * Fetch the next token from the XER/XML stream.
  53. */
  54. ssize_t
  55. xer_next_token(int *stateContext, const void *buffer, size_t size, pxer_chunk_type_e *ch_type) {
  56. struct xer__cb_arg arg;
  57. int new_stateContext = *stateContext;
  58. ssize_t ret;
  59. arg.callback_not_invoked = 1;
  60. ret = pxml_parse(&new_stateContext, buffer, size, xer__token_cb, &arg);
  61. if(ret < 0) return -1;
  62. if(arg.callback_not_invoked) {
  63. assert(ret == 0); /* No data was consumed */
  64. *ch_type = PXER_WMORE;
  65. return 0; /* Try again with more data */
  66. } else {
  67. assert(arg.chunk_size);
  68. assert(arg.chunk_buf == buffer);
  69. }
  70. /*
  71. * Translate the XML chunk types into more convenient ones.
  72. */
  73. switch(arg.chunk_type) {
  74. case PXML_TEXT:
  75. *ch_type = PXER_TEXT;
  76. break;
  77. case PXML_TAG:
  78. *ch_type = PXER_WMORE;
  79. return 0; /* Want more */
  80. case PXML_TAG_END:
  81. *ch_type = PXER_TAG;
  82. break;
  83. case PXML_COMMENT:
  84. case PXML_COMMENT_END:
  85. *ch_type = PXER_COMMENT;
  86. break;
  87. }
  88. *stateContext = new_stateContext;
  89. return arg.chunk_size;
  90. }
  91. #define CSLASH 0x2f /* '/' */
  92. #define LANGLE 0x3c /* '<' */
  93. #define RANGLE 0x3e /* '>' */
  94. xer_check_tag_e
  95. xer_check_tag(const void *buf_ptr, int size, const char *need_tag) {
  96. const char *buf = (const char *)buf_ptr;
  97. const char *end;
  98. xer_check_tag_e ct = XCT_OPENING;
  99. if(size < 2 || buf[0] != LANGLE || buf[size-1] != RANGLE) {
  100. if(size >= 2)
  101. ASN_DEBUG("Broken XML tag: \"%c...%c\"",
  102. buf[0], buf[size - 1]);
  103. return XCT_BROKEN;
  104. }
  105. /*
  106. * Determine the tag class.
  107. */
  108. if(buf[1] == CSLASH) {
  109. buf += 2; /* advance past "</" */
  110. size -= 3; /* strip "</" and ">" */
  111. ct = XCT_CLOSING;
  112. if(size > 0 && buf[size-1] == CSLASH)
  113. return XCT_BROKEN; /* </abc/> */
  114. } else {
  115. buf++; /* advance past "<" */
  116. size -= 2; /* strip "<" and ">" */
  117. if(size > 0 && buf[size-1] == CSLASH) {
  118. ct = XCT_BOTH;
  119. size--; /* One more, for "/" */
  120. }
  121. }
  122. /* Sometimes we don't care about the tag */
  123. if(!need_tag || !*need_tag)
  124. return (xer_check_tag_e)(XCT__UNK__MASK | ct);
  125. /*
  126. * Determine the tag name.
  127. */
  128. for(end = buf + size; buf < end; buf++, need_tag++) {
  129. int b = *buf, n = *need_tag;
  130. if(b != n) {
  131. if(n == 0) {
  132. switch(b) {
  133. case 0x09: case 0x0a: case 0x0c: case 0x0d:
  134. case 0x20:
  135. /* "<abc def/>": whitespace is normal */
  136. return ct;
  137. }
  138. }
  139. return (xer_check_tag_e)(XCT__UNK__MASK | ct);
  140. }
  141. if(b == 0)
  142. return XCT_BROKEN; /* Embedded 0 in buf?! */
  143. }
  144. if(*need_tag)
  145. return (xer_check_tag_e)(XCT__UNK__MASK | ct);
  146. return ct;
  147. }
  148. #undef ADVANCE
  149. #define ADVANCE(num_bytes) do { \
  150. size_t num = (num_bytes); \
  151. buf_ptr = ((const char *)buf_ptr) + num; \
  152. size -= num; \
  153. consumed_myself += num; \
  154. } while(0)
  155. #undef RETURN
  156. #define RETURN(_code) do { \
  157. rval.code = _code; \
  158. rval.consumed = consumed_myself; \
  159. if(rval.code != RC_OK) \
  160. ASN_DEBUG("Failed with %d", rval.code); \
  161. return rval; \
  162. } while(0)
  163. #define XER_GOT_BODY(chunk_buf, chunk_size, size) do { \
  164. ssize_t converted_size = body_receiver \
  165. (struct_key, chunk_buf, chunk_size, \
  166. (size_t)chunk_size < size); \
  167. if(converted_size == -1) RETURN(RC_FAIL); \
  168. if(converted_size == 0 \
  169. && size == (size_t)chunk_size) \
  170. RETURN(RC_WMORE); \
  171. chunk_size = converted_size; \
  172. } while(0)
  173. #define XER_GOT_EMPTY() do { \
  174. if(body_receiver(struct_key, 0, 0, size > 0) == -1) \
  175. RETURN(RC_FAIL); \
  176. } while(0)
  177. /*
  178. * Generalized function for decoding the primitive values.
  179. */
  180. asn_dec_rval_t
  181. xer_decode_general(const asn_codec_ctx_t *opt_codec_ctx,
  182. asn_struct_ctx_t *ctx, /* Type decoder context */
  183. void *struct_key,
  184. const char *xml_tag, /* Expected XML tag */
  185. const void *buf_ptr, size_t size,
  186. int (*opt_unexpected_tag_decoder)
  187. (void *struct_key, const void *chunk_buf, size_t chunk_size),
  188. ssize_t (*body_receiver)
  189. (void *struct_key, const void *chunk_buf, size_t chunk_size,
  190. int have_more)
  191. ) {
  192. asn_dec_rval_t rval;
  193. ssize_t consumed_myself = 0;
  194. (void)opt_codec_ctx;
  195. /*
  196. * Phases of XER/XML processing:
  197. * Phase 0: Check that the opening tag matches our expectations.
  198. * Phase 1: Processing body and reacting on closing tag.
  199. */
  200. if(ctx->phase > 1) RETURN(RC_FAIL);
  201. for(;;) {
  202. pxer_chunk_type_e ch_type; /* XER chunk type */
  203. ssize_t ch_size; /* Chunk size */
  204. xer_check_tag_e tcv; /* Tag check value */
  205. /*
  206. * Get the next part of the XML stream.
  207. */
  208. ch_size = xer_next_token(&ctx->context, buf_ptr, size,
  209. &ch_type);
  210. if(ch_size == -1) {
  211. RETURN(RC_FAIL);
  212. } else {
  213. switch(ch_type) {
  214. case PXER_WMORE:
  215. RETURN(RC_WMORE);
  216. case PXER_COMMENT: /* Got XML comment */
  217. ADVANCE(ch_size); /* Skip silently */
  218. continue;
  219. case PXER_TEXT:
  220. if(ctx->phase == 0) {
  221. /*
  222. * We have to ignore whitespace here,
  223. * but in order to be forward compatible
  224. * with EXTENDED-XER (EMBED-VALUES, #25)
  225. * any text is just ignored here.
  226. */
  227. } else {
  228. XER_GOT_BODY(buf_ptr, ch_size, size);
  229. }
  230. ADVANCE(ch_size);
  231. continue;
  232. case PXER_TAG:
  233. break; /* Check the rest down there */
  234. }
  235. }
  236. assert(ch_type == PXER_TAG && size);
  237. tcv = xer_check_tag(buf_ptr, ch_size, xml_tag);
  238. /*
  239. * Phase 0:
  240. * Expecting the opening tag
  241. * for the type being processed.
  242. * Phase 1:
  243. * Waiting for the closing XML tag.
  244. */
  245. switch(tcv) {
  246. case XCT_BOTH:
  247. if(ctx->phase) break;
  248. /* Finished decoding of an empty element */
  249. XER_GOT_EMPTY();
  250. ADVANCE(ch_size);
  251. ctx->phase = 2; /* Phase out */
  252. RETURN(RC_OK);
  253. case XCT_OPENING:
  254. if(ctx->phase) break;
  255. ADVANCE(ch_size);
  256. ctx->phase = 1; /* Processing body phase */
  257. continue;
  258. case XCT_CLOSING:
  259. if(!ctx->phase) break;
  260. ADVANCE(ch_size);
  261. ctx->phase = 2; /* Phase out */
  262. RETURN(RC_OK);
  263. case XCT_UNKNOWN_BO:
  264. /*
  265. * Certain tags in the body may be expected.
  266. */
  267. if(opt_unexpected_tag_decoder
  268. && opt_unexpected_tag_decoder(struct_key,
  269. buf_ptr, ch_size) >= 0) {
  270. /* Tag's processed fine */
  271. ADVANCE(ch_size);
  272. if(!ctx->phase) {
  273. /* We are not expecting
  274. * the closing tag anymore. */
  275. ctx->phase = 2; /* Phase out */
  276. RETURN(RC_OK);
  277. }
  278. continue;
  279. }
  280. /* Fall through */
  281. default:
  282. break; /* Unexpected tag */
  283. }
  284. ASN_DEBUG("Unexpected XML tag (expected \"%s\")", xml_tag);
  285. break; /* Dark and mysterious things have just happened */
  286. }
  287. RETURN(RC_FAIL);
  288. }
  289. size_t
  290. xer_whitespace_span(const void *chunk_buf, size_t chunk_size) {
  291. const char *p = (const char *)chunk_buf;
  292. const char *pend = p + chunk_size;
  293. for(; p < pend; p++) {
  294. switch(*p) {
  295. /* X.693, #8.1.4
  296. * HORISONTAL TAB (9)
  297. * LINE FEED (10)
  298. * CARRIAGE RETURN (13)
  299. * SPACE (32)
  300. */
  301. case 0x09: case 0x0a: case 0x0d: case 0x20:
  302. continue;
  303. default:
  304. break;
  305. }
  306. break;
  307. }
  308. return (p - (const char *)chunk_buf);
  309. }
  310. /*
  311. * This is a vastly simplified, non-validating XML tree skipper.
  312. */
  313. int
  314. xer_skip_unknown(xer_check_tag_e tcv, ber_tlv_len_t *depth) {
  315. assert(*depth > 0);
  316. switch(tcv) {
  317. case XCT_BOTH:
  318. case XCT_UNKNOWN_BO:
  319. /* These negate each other. */
  320. return 0;
  321. case XCT_OPENING:
  322. case XCT_UNKNOWN_OP:
  323. ++(*depth);
  324. return 0;
  325. case XCT_CLOSING:
  326. case XCT_UNKNOWN_CL:
  327. if(--(*depth) == 0)
  328. return (tcv == XCT_CLOSING) ? 2 : 1;
  329. return 0;
  330. default:
  331. return -1;
  332. }
  333. }