asn_codecs_prim.c 7.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317
  1. /*-
  2. * Copyright (c) 2003, 2004 Lev Walkin <vlm@lionet.info>. All rights reserved.
  3. * Redistribution and modifications are permitted subject to BSD license.
  4. */
  5. #include <asn_internal.h>
  6. #include <asn_codecs_prim.h>
  7. #include <errno.h>
  8. /*
  9. * Decode an always-primitive type.
  10. */
  11. asn_dec_rval_t
  12. ber_decode_primitive(const asn_codec_ctx_t *opt_codec_ctx,
  13. const asn_TYPE_descriptor_t *td, void **sptr,
  14. const void *buf_ptr, size_t size, int tag_mode) {
  15. ASN__PRIMITIVE_TYPE_t *st = (ASN__PRIMITIVE_TYPE_t *)*sptr;
  16. asn_dec_rval_t rval;
  17. ber_tlv_len_t length = 0; /* =0 to avoid [incorrect] warning. */
  18. /*
  19. * If the structure is not there, allocate it.
  20. */
  21. if(st == NULL) {
  22. st = (ASN__PRIMITIVE_TYPE_t *)CALLOC(1, sizeof(*st));
  23. if(st == NULL) ASN__DECODE_FAILED;
  24. *sptr = (void *)st;
  25. }
  26. ASN_DEBUG("Decoding %s as plain primitive (tm=%d)",
  27. td->name, tag_mode);
  28. /*
  29. * Check tags and extract value length.
  30. */
  31. rval = ber_check_tags(opt_codec_ctx, td, 0, buf_ptr, size,
  32. tag_mode, 0, &length, 0);
  33. if(rval.code != RC_OK)
  34. return rval;
  35. ASN_DEBUG("%s length is %d bytes", td->name, (int)length);
  36. /*
  37. * Make sure we have this length.
  38. */
  39. buf_ptr = ((const char *)buf_ptr) + rval.consumed;
  40. size -= rval.consumed;
  41. if(length > (ber_tlv_len_t)size) {
  42. rval.code = RC_WMORE;
  43. rval.consumed = 0;
  44. return rval;
  45. }
  46. st->size = (int)length;
  47. /* The following better be optimized away. */
  48. if(sizeof(st->size) != sizeof(length)
  49. && (ber_tlv_len_t)st->size != length) {
  50. st->size = 0;
  51. ASN__DECODE_FAILED;
  52. }
  53. st->buf = (uint8_t *)MALLOC(length + 1);
  54. if(!st->buf) {
  55. st->size = 0;
  56. ASN__DECODE_FAILED;
  57. }
  58. memcpy(st->buf, buf_ptr, length);
  59. st->buf[length] = '\0'; /* Just in case */
  60. rval.code = RC_OK;
  61. rval.consumed += length;
  62. ASN_DEBUG("Took %ld/%ld bytes to encode %s",
  63. (long)rval.consumed,
  64. (long)length, td->name);
  65. return rval;
  66. }
  67. /*
  68. * Encode an always-primitive type using DER.
  69. */
  70. asn_enc_rval_t
  71. der_encode_primitive(const asn_TYPE_descriptor_t *td, const void *sptr,
  72. int tag_mode, ber_tlv_tag_t tag,
  73. asn_app_consume_bytes_f *cb, void *app_key) {
  74. asn_enc_rval_t erval;
  75. const ASN__PRIMITIVE_TYPE_t *st = (const ASN__PRIMITIVE_TYPE_t *)sptr;
  76. ASN_DEBUG("%s %s as a primitive type (tm=%d)",
  77. cb?"Encoding":"Estimating", td->name, tag_mode);
  78. erval.encoded = der_write_tags(td, st->size, tag_mode, 0, tag,
  79. cb, app_key);
  80. ASN_DEBUG("%s wrote tags %d", td->name, (int)erval.encoded);
  81. if(erval.encoded == -1) {
  82. erval.failed_type = td;
  83. erval.structure_ptr = sptr;
  84. return erval;
  85. }
  86. if(cb && st->buf) {
  87. if(cb(st->buf, st->size, app_key) < 0) {
  88. erval.encoded = -1;
  89. erval.failed_type = td;
  90. erval.structure_ptr = sptr;
  91. return erval;
  92. }
  93. } else {
  94. assert(st->buf || st->size == 0);
  95. }
  96. erval.encoded += st->size;
  97. ASN__ENCODED_OK(erval);
  98. }
  99. void
  100. ASN__PRIMITIVE_TYPE_free(const asn_TYPE_descriptor_t *td, void *sptr,
  101. enum asn_struct_free_method method) {
  102. ASN__PRIMITIVE_TYPE_t *st = (ASN__PRIMITIVE_TYPE_t *)sptr;
  103. if(!td || !sptr)
  104. return;
  105. ASN_DEBUG("Freeing %s as a primitive type", td->name);
  106. if(st->buf)
  107. FREEMEM(st->buf);
  108. switch(method) {
  109. case ASFM_FREE_EVERYTHING:
  110. FREEMEM(sptr);
  111. break;
  112. case ASFM_FREE_UNDERLYING:
  113. break;
  114. case ASFM_FREE_UNDERLYING_AND_RESET:
  115. memset(sptr, 0, sizeof(ASN__PRIMITIVE_TYPE_t));
  116. break;
  117. }
  118. }
  119. /*
  120. * Local internal type passed around as an argument.
  121. */
  122. struct xdp_arg_s {
  123. const asn_TYPE_descriptor_t *type_descriptor;
  124. void *struct_key;
  125. xer_primitive_body_decoder_f *prim_body_decoder;
  126. int decoded_something;
  127. int want_more;
  128. };
  129. /*
  130. * Since some kinds of primitive values can be encoded using value-specific
  131. * tags (<MINUS-INFINITY>, <enum-element>, etc), the primitive decoder must
  132. * be supplied with such tags to parse them as needed.
  133. */
  134. static int
  135. xer_decode__unexpected_tag(void *key, const void *chunk_buf, size_t chunk_size) {
  136. struct xdp_arg_s *arg = (struct xdp_arg_s *)key;
  137. enum xer_pbd_rval bret;
  138. /*
  139. * The chunk_buf is guaranteed to start at '<'.
  140. */
  141. assert(chunk_size && ((const char *)chunk_buf)[0] == 0x3c);
  142. /*
  143. * Decoding was performed once already. Prohibit doing it again.
  144. */
  145. if(arg->decoded_something)
  146. return -1;
  147. bret = arg->prim_body_decoder(arg->type_descriptor,
  148. arg->struct_key, chunk_buf, chunk_size);
  149. switch(bret) {
  150. case XPBD_SYSTEM_FAILURE:
  151. case XPBD_DECODER_LIMIT:
  152. case XPBD_BROKEN_ENCODING:
  153. break;
  154. case XPBD_BODY_CONSUMED:
  155. /* Tag decoded successfully */
  156. arg->decoded_something = 1;
  157. /* Fall through */
  158. case XPBD_NOT_BODY_IGNORE: /* Safe to proceed further */
  159. return 0;
  160. }
  161. return -1;
  162. }
  163. static ssize_t
  164. xer_decode__primitive_body(void *key, const void *chunk_buf, size_t chunk_size, int have_more) {
  165. struct xdp_arg_s *arg = (struct xdp_arg_s *)key;
  166. enum xer_pbd_rval bret;
  167. size_t lead_wsp_size;
  168. if(arg->decoded_something) {
  169. if(xer_whitespace_span(chunk_buf, chunk_size) == chunk_size) {
  170. /*
  171. * Example:
  172. * "<INTEGER>123<!--/--> </INTEGER>"
  173. * ^- chunk_buf position.
  174. */
  175. return chunk_size;
  176. }
  177. /*
  178. * Decoding was done once already. Prohibit doing it again.
  179. */
  180. return -1;
  181. }
  182. if(!have_more) {
  183. /*
  184. * If we've received something like "1", we can't really
  185. * tell whether it is really `1` or `123`, until we know
  186. * that there is no more data coming.
  187. * The have_more argument will be set to 1 once something
  188. * like this is available to the caller of this callback:
  189. * "1<tag_start..."
  190. */
  191. arg->want_more = 1;
  192. return -1;
  193. }
  194. lead_wsp_size = xer_whitespace_span(chunk_buf, chunk_size);
  195. chunk_buf = (const char *)chunk_buf + lead_wsp_size;
  196. chunk_size -= lead_wsp_size;
  197. bret = arg->prim_body_decoder(arg->type_descriptor,
  198. arg->struct_key, chunk_buf, chunk_size);
  199. switch(bret) {
  200. case XPBD_SYSTEM_FAILURE:
  201. case XPBD_DECODER_LIMIT:
  202. case XPBD_BROKEN_ENCODING:
  203. break;
  204. case XPBD_BODY_CONSUMED:
  205. /* Tag decoded successfully */
  206. arg->decoded_something = 1;
  207. /* Fall through */
  208. case XPBD_NOT_BODY_IGNORE: /* Safe to proceed further */
  209. return lead_wsp_size + chunk_size;
  210. }
  211. return -1;
  212. }
  213. asn_dec_rval_t
  214. xer_decode_primitive(const asn_codec_ctx_t *opt_codec_ctx,
  215. const asn_TYPE_descriptor_t *td, void **sptr,
  216. size_t struct_size, const char *opt_mname,
  217. const void *buf_ptr, size_t size,
  218. xer_primitive_body_decoder_f *prim_body_decoder) {
  219. const char *xml_tag = opt_mname ? opt_mname : td->xml_tag;
  220. asn_struct_ctx_t s_ctx;
  221. struct xdp_arg_s s_arg;
  222. asn_dec_rval_t rc;
  223. /*
  224. * Create the structure if does not exist.
  225. */
  226. if(!*sptr) {
  227. *sptr = CALLOC(1, struct_size);
  228. if(!*sptr) ASN__DECODE_FAILED;
  229. }
  230. memset(&s_ctx, 0, sizeof(s_ctx));
  231. s_arg.type_descriptor = td;
  232. s_arg.struct_key = *sptr;
  233. s_arg.prim_body_decoder = prim_body_decoder;
  234. s_arg.decoded_something = 0;
  235. s_arg.want_more = 0;
  236. rc = xer_decode_general(opt_codec_ctx, &s_ctx, &s_arg,
  237. xml_tag, buf_ptr, size,
  238. xer_decode__unexpected_tag, xer_decode__primitive_body);
  239. switch(rc.code) {
  240. case RC_OK:
  241. if(!s_arg.decoded_something) {
  242. char ch;
  243. ASN_DEBUG("Primitive body is not recognized, "
  244. "supplying empty one");
  245. /*
  246. * Decoding opportunity has come and gone.
  247. * Where's the result?
  248. * Try to feed with empty body, see if it eats it.
  249. */
  250. if(prim_body_decoder(s_arg.type_descriptor,
  251. s_arg.struct_key, &ch, 0)
  252. != XPBD_BODY_CONSUMED) {
  253. /*
  254. * This decoder does not like empty stuff.
  255. */
  256. ASN__DECODE_FAILED;
  257. }
  258. }
  259. break;
  260. case RC_WMORE:
  261. /*
  262. * Redo the whole thing later.
  263. * We don't have a context to save intermediate parsing state.
  264. */
  265. rc.consumed = 0;
  266. break;
  267. case RC_FAIL:
  268. rc.consumed = 0;
  269. if(s_arg.want_more)
  270. rc.code = RC_WMORE;
  271. else
  272. ASN__DECODE_FAILED;
  273. break;
  274. }
  275. return rc;
  276. }