LCOV - code coverage report
Current view: top level - zxid - zxlibdec.c (source / functions) Hit Total Coverage
Test: ZXID Code Coverage Lines: 288 331 87.0 %
Date: 2010-12-19 Functions: 17 17 100.0 %
Branches: 182 259 70.3 %

           Branch data     Line data    Source code
       1                 :            : /* zxlibdec.c  -  Utility functions for generated decoders
       2                 :            :  * Copyright (c) 2010 Sampo Kellomaki (sampo@iki.fi), All Rights Reserved.
       3                 :            :  * Copyright (c) 2006-2009 Symlabs (symlabs@symlabs.com), All Rights Reserved.
       4                 :            :  * Author: Sampo Kellomaki (sampo@iki.fi)
       5                 :            :  * This is confidential unpublished proprietary source code of the author.
       6                 :            :  * NO WARRANTY, not even implied warranties. Contains trade secrets.
       7                 :            :  * Distribution prohibited unless authorized in writing.
       8                 :            :  * Licensed under Apache License 2.0, see file COPYING.
       9                 :            :  * $Id: zxlib.c,v 1.41 2009-11-24 23:53:40 sampo Exp $
      10                 :            :  *
      11                 :            :  * 28.5.2006, created --Sampo
      12                 :            :  * 8.8.2006,  moved lookup functions to generated code --Sampo
      13                 :            :  * 12.8.2006, added special scanning of xmlns to avoid backtracking elem recognition --Sampo
      14                 :            :  * 26.8.2006, significant Common Subexpression Elimination (CSE) --Sampo
      15                 :            :  * 30.9.2007, more CSE --Sampo
      16                 :            :  * 7.10.2008, added documentation --Sampo
      17                 :            :  * 26.5.2010, added XML parse error reporting --Sampo
      18                 :            :  * 27.10.2010, forked from zxlib.c, re-engineered namespace handling --Sampo
      19                 :            :  * 20.11.2010, reengineered for unified simplifed decoder --Sampo
      20                 :            :  */
      21                 :            : 
      22                 :            : #include "platform.h"  /* needed on Win32 for snprintf(), va_copy() et al. */
      23                 :            : 
      24                 :            : //#include <pthread.h>
      25                 :            : //#ifndef MACOSX
      26                 :            : //#include <malloc.h>
      27                 :            : //#endif
      28                 :            : #include <memory.h>
      29                 :            : #include <string.h>
      30                 :            : #include <stdarg.h>
      31                 :            : #include <stdio.h>
      32                 :            : #include <stdlib.h>
      33                 :            : 
      34                 :            : #include "errmac.h"
      35                 :            : #include "zx.h"
      36                 :            : #include "c/zx-data.h"
      37                 :            : #include "c/zx-ns.h"
      38                 :            : 
      39                 :            : /*() Format error message describing an XML parse error. The buf argument
      40                 :            :  * should be at leaset 256 bytes for satisfactory results. */
      41                 :            : 
      42                 :            : /* Called by:  covimp_test, zxid_wsp_validate */
      43                 :            : int zx_format_parse_error(struct zx_ctx* ctx, char* buf, int siz, char* logkey)
      44                 :          1 : {
      45                 :            :   int at, end, start, len;
      46                 :          1 :   end = ctx->lim - ctx->bas;
      47                 :          1 :   at = MIN(ctx->p - ctx->bas, end);
      48                 :          1 :   start = MAX(0,at-30);
      49                 :          1 :   len = MIN(at+30, end) - start;    
      50   [ +  -  -  + ]:          1 :   len = snprintf(buf, siz, "%s: Parse error at char %d/%d (prev char, char, next char: 0x%02x 0x%02x 0x%02x)\n%.*s\n%.*s^\n", logkey, at, end, at > 0 ? ctx->p[-1]:0, ctx->p[0], at < end ? ctx->p[1]:0, len, ctx->bas + start, at-start, "-----------------------------------------------");
      51                 :          1 :   buf[siz-1] = 0; /* must terminate manually as on win32 nul is not guaranteed */
      52                 :          1 :   return len;
      53                 :            : }
      54                 :            : 
      55                 :            : /* Called by:  covimp_test, zx_dec_attr_val x2, zx_scan_elem_end, zx_scan_pi_or_comment, zx_scan_xmlns x2 */
      56                 :            : void zx_xml_parse_err(struct zx_ctx* c, char quote, const char* func, const char* msg)
      57                 :          1 : {
      58                 :          1 :   const char* errloc = MAX(c->p - 20, c->bas);
      59                 :          1 :   ERR("%s: %s: char(%c) pos=%d (%.*s)", func, msg, quote,
      60                 :            :       c->p - c->bas, MIN(c->lim - errloc, 40), errloc);
      61                 :          1 : }
      62                 :            : 
      63                 :            : /* Called by:  zx_xmlns_decl */
      64                 :            : void zx_xml_parse_dbg(struct zx_ctx* c, char quote, const char* func, const char* msg)
      65                 :       4090 : {
      66                 :       4090 :   const char* errloc = MAX(c->p - 20, c->bas);
      67   [ +  +  -  + ]:       4090 :   D("%s: %s: char(%c) pos=%d (%.*s)", func, msg, quote,
      68                 :            :     c->p - c->bas, MIN(c->lim - errloc, 40), errloc);
      69                 :       4090 : }
      70                 :            : 
      71                 :            : /* --------------------- D e c o d e r ---------------------- */
      72                 :            : 
      73                 :            : /* Called by:  zx_DEC_elem */
      74                 :            : static int zx_scan_data(struct zx_ctx* c, struct zx_elem_s* el)
      75                 :     209730 : {
      76                 :            :   struct zx_str* ss;
      77                 :     209730 :   const char* d = c->p;
      78         [ +  - ]:     209730 :   if (c->p)
      79         [ +  + ]:     209730 :     ZX_LOOK_FOR(c,'<');
      80                 :     188889 :   ss = ZX_ZALLOC(c, struct zx_str);
      81                 :     188889 :   ss->len = c->p - d;
      82                 :     188889 :   ss->s = (char*)d;
      83                 :     188889 :   ss->tok = ZX_TOK_DATA;
      84                 :     188889 :   ss->n = &el->kids->g;
      85                 :     188889 :   el->kids = (struct zx_elem_s*)ss;
      86                 :     188889 :   return 1;
      87                 :            : 
      88                 :      20841 :  look_for_not_found:
      89                 :            :   /*zx_xml_parse_err(c, '<', (const char*)__FUNCTION__, "look for not found");  -- Causes bogus warning in end of buffer. */
      90                 :      20841 :   return 0;
      91                 :            : }
      92                 :            : 
      93                 :            : /* Called by:  zx_DEC_elem */
      94                 :            : static int zx_scan_pi_or_comment(struct zx_ctx* c)
      95                 :         42 : {
      96                 :            :   const char* name;
      97                 :            :   char quote;
      98                 :            : 
      99      [ +  +  - ]:         42 :   switch (*c->p) {
     100                 :            :   case '?':  /* processing instruction <?xml ... ?> */
     101                 :         32 :     name = c->p-1;
     102                 :            :     DD("Processing Instruction detected (%.*s)", 5, name);
     103                 :            :     while (1) {
     104                 :         32 :       quote = '>';
     105         [ +  - ]:         32 :       ZX_LOOK_FOR(c,'>');
     106         [ -  + ]:         32 :       if (c->p[-1] == '?')
     107                 :         32 :         break;
     108                 :          0 :     }
     109                 :         32 :     ++c->p;
     110                 :            :     DD("Processing Instruction scanned (%.*s)", c->p-name, name);
     111                 :            :     /*ZX_PI_DEC_EXT(pi);*/
     112                 :         32 :     return 0;
     113                 :            :   case '!':  /* comment <!-- ... --> or <!DOCTYPE...> */
     114                 :         10 :     name = c->p-1;
     115         [ -  + ]:         10 :     if (!memcmp(c->p+1, "DOCTYPE", sizeof("DOCTYPE")-1)) {
     116   [ #  #  #  # ]:          0 :       D("DOCTYPE detected (%.*s)", 60, c->p-1);
     117         [ #  # ]:          0 :       ZX_LOOK_FOR(c,'>');
     118                 :          0 :       ++c->p;
     119   [ #  #  #  # ]:          0 :       D("DOCTYPE scanned (%.*s)", c->p-name, name);
     120                 :          0 :       return 0;
     121                 :            :     }
     122                 :         10 :     c->p += 2;
     123   [ +  -  -  + ]:         10 :     if (c->p[-1] != '-' || c->p[0] != '-') {
     124                 :          0 :       c->p -= 3;
     125                 :          0 :       return 1;
     126                 :            :     }
     127   [ -  +  #  # ]:         10 :     D("Comment detected (%.*s)", 8, name);
     128                 :         10 :     c->p += 2;
     129                 :            :     while (1) {
     130                 :         10 :       quote = '>';
     131         [ +  - ]:         10 :       ZX_LOOK_FOR(c,'>');
     132   [ +  -  -  + ]:         10 :       if (c->p[-2] == '-' && c->p[-1] == '-') {
     133                 :         10 :         break;
     134                 :            :       }
     135                 :          0 :     }
     136                 :         10 :     ++c->p;
     137   [ -  +  #  # ]:         10 :     D("Comment scanned (%.*s)", c->p-name, name);
     138                 :            :     /*ZX_COMMENT_DEC_EXT(comment);*/
     139                 :         10 :     return 0;
     140                 :            :   }
     141                 :          0 :   return 1;
     142                 :          0 :  look_for_not_found:
     143                 :          0 :   zx_xml_parse_err(c, quote, (const char*)__FUNCTION__, "look for not found");
     144                 :          0 :   return 1;
     145                 :            : }
     146                 :            : 
     147                 :            : /*() Assuming current c->p points to a name, scan until end of the name.
     148                 :            :  * Called from innards for dec-templ.c for CSE. Leaves c->p pointing to char after name. */
     149                 :            : 
     150                 :            : /* Called by:  zx_el_lookup */
     151                 :            : static const char* zx_scan_elem_start(struct zx_ctx* c, const char* func)
     152                 :     730174 : {
     153                 :     730174 :   const char* name = c->p;
     154                 :     730174 :   int len = strcspn(c->p, " >/\n\r\t");
     155                 :     730174 :   c->p += len;
     156                 :            :   /*for (++c->p; *c->p && !ONE_OF_6(*c->p, ' ', '>', '/', '\n', '\r', '\t'); ++c->p) ;*/
     157         [ +  - ]:     730174 :   if (*c->p)
     158                 :     730174 :     return name;
     159                 :          0 :   ERR("%s: Incomplete %s", func, name);
     160                 :          0 :   return 0;
     161                 :            : }
     162                 :            : 
     163                 :            : /*() End of tag detection called from innards for dec-templ.c for CSE. */
     164                 :            : 
     165                 :            : /* Called by:  zx_DEC_elem */
     166                 :            : static int zx_scan_elem_end(struct zx_ctx* c, const char* start, const char* func)
     167                 :     711871 : {
     168                 :            :   const char* name;
     169                 :            :   const char* errloc;
     170                 :     711871 :   ++c->p;
     171                 :     711871 :   name = c->p;
     172         [ +  - ]:     711871 :   ZX_LOOK_FOR(c,'>');
     173         [ +  + ]:     711871 :   if (memcmp(start, name, c->p-name))        {
     174                 :         12 :     errloc = MAX(c->p - 20, c->bas);
     175                 :         12 :     ERR("%s: Mismatching close tag(%.*s) pos=%d (%.*s)", func, c->p-name, name, c->p - c->bas, MIN(c->lim - errloc, 40), errloc);
     176                 :         12 :     ++c->p;
     177                 :         12 :     return 0;
     178                 :            :   }
     179                 :     711859 :   return 1;
     180                 :            : 
     181                 :          0 : look_for_not_found:
     182                 :          0 :   zx_xml_parse_err(c, '>', func, "char not found");
     183                 :          0 :   return 0;
     184                 :            : }
     185                 :            : 
     186                 :            : /*() Check the child element ordering of a token against schema.
     187                 :            :  * Returns 0 if ordering is good. If ordering is bad, returns index to
     188                 :            :  * the offending child element. This check does not verify whether all
     189                 :            :  * mandatory child elements are present - it merely checks that the
     190                 :            :  * order is right. */
     191                 :            : 
     192                 :            : /* Called by:  zx_reverse_elem_lists */
     193                 :            : static int zx_chk_el_ord(struct zx_elem_s* x)
     194                 :     743797 : {
     195                 :            :   int i,j,n;
     196                 :            :   struct zx_el_tok* et;
     197                 :            :   struct zx_el_tok* ef;
     198                 :     743797 :   struct zx_el_desc* ed = zx_el_desc_lookup(x->g.tok);
     199         [ +  + ]:     743797 :   if (!ed)
     200                 :      12544 :     return 0;
     201                 :     731253 :   x = x->kids;
     202         [ +  + ]:    1611544 :   for (n = i = j = 0; x; i = j, x = (struct zx_elem_s*)x->g.n) {
     203                 :     892046 :     ++n;
     204         [ +  + ]:     892046 :     if (x->g.tok == ZX_TOK_DATA)
     205                 :     172111 :       continue;
     206         [ +  + ]:    2726898 :     for (j = i; ed->el_order[j] != ZX_TOK_NOT_FOUND; ++j)
     207         [ +  + ]:    2715143 :       if (x->g.tok == ed->el_order[j])
     208                 :     708180 :         break;
     209         [ +  + ]:     719935 :     if (ed->el_order[j] == ZX_TOK_NOT_FOUND) {
     210   [ +  +  -  + ]:      17046 :       if (x->g.tok == ZX_TOK_NOT_FOUND || !IN_RANGE(x->g.tok & ZX_TOK_TOK_MASK, 0, zx__ELEM_MAX)) {
     211   [ +  -  +  - ]:       5291 :         ef = zx_el_tab + MINMAX(ed->tok & ZX_TOK_TOK_MASK, 0, zx__ELEM_MAX);
     212                 :       5291 :         INFO("Unknown <%.*s> token(0x%06x) as %d. child of <%s> 0x%06x (%d,%d)", x->g.len, x->g.s, x->g.tok, n, ef->name, ed->tok, i, j);
     213                 :            :       } else {
     214                 :       6464 :         et = zx_el_tab + (x->g.tok & ZX_TOK_TOK_MASK);
     215   [ +  -  +  - ]:       6464 :         ef = zx_el_tab + MINMAX(ed->tok & ZX_TOK_TOK_MASK, 0, zx__ELEM_MAX);
     216                 :       6464 :         ERR("Known <%s> tok(0x%06x) in wrong place as %d. child of <%s> tok(0x%06x) (%d,%d)", et->name, x->g.tok, n, ef->name, ed->tok, i, j);
     217                 :            :       }
     218                 :      11755 :       return n;
     219                 :            :     }
     220                 :            :   }
     221                 :     719498 :   return 0;
     222                 :            : }
     223                 :            : 
     224                 :            : /*() Insert an attribute to element's attribtue list in canoncically sorted
     225                 :            :  * place, i.e. no namespace sorts first, namespaced attribute sort by
     226                 :            :  * namespace URI (not namespace prefix). Assumes the attribute
     227                 :            :  * list has so far been sorted. Used as part of insertion sort. */
     228                 :            : 
     229                 :            : /* Called by:  zx_reverse_elem_lists */
     230                 :            : struct zx_attr_s* zx_ord_ins_at(struct zx_elem_s* x, struct zx_attr_s* in_at)
     231                 :     174048 : {
     232                 :            :   struct zx_attr_s* at;
     233                 :            :   struct zx_attr_s** atp;
     234                 :            :   const char* at_name;
     235                 :            :   const char* in_at_name;
     236                 :            :   const char* p;
     237                 :            :   int res, at_name_len, in_at_name_len;
     238                 :            : 
     239                 :     174048 :   atp = &x->attr;
     240         [ +  + ]:     176913 :   for (at = x->attr; at; atp = (struct zx_attr_s**)&at->g.n, at = (struct zx_attr_s*)at->g.n) {
     241   [ +  +  +  +  :     175147 :     if (!in_at->ns && IN_RANGE((in_at->g.tok & ZX_TOK_NS_MASK)>>ZX_TOK_NS_SHIFT, 1, zx__NS_MAX))
                   +  - ]
     242                 :       1154 :       in_at->ns = zx_ns_tab + ((in_at->g.tok & ZX_TOK_NS_MASK)>>ZX_TOK_NS_SHIFT);
     243         [ +  + ]:     175147 :     if (in_at->ns) {
     244   [ +  +  +  +  :      63823 :       if (!at->ns && IN_RANGE((at->g.tok & ZX_TOK_NS_MASK)>>ZX_TOK_NS_SHIFT, 1, zx__NS_MAX))
                   +  - ]
     245                 :       1154 :         at->ns = zx_ns_tab + ((at->g.tok & ZX_TOK_NS_MASK)>>ZX_TOK_NS_SHIFT);
     246         [ +  + ]:      63823 :       if (at->ns) {
     247         [ +  + ]:      63355 :         if (at->ns != in_at->ns) {
     248                 :      30802 :           res = memcmp(at->ns->url, in_at->ns->url, MIN(at->ns->url_len, in_at->ns->url_len));
     249         [ +  - ]:      30802 :           if (res > 0)
     250                 :      30802 :             break;
     251         [ #  # ]:          0 :           if (res < 0)
     252                 :          0 :             continue;
     253         [ #  # ]:          0 :           if (at->ns->url_len > in_at->ns->url_len)
     254                 :          0 :             break;
     255         [ #  # ]:          0 :           if (at->ns->url_len < in_at->ns->url_len)
     256                 :          0 :             continue;
     257                 :            :         }
     258                 :            :       } else
     259                 :        468 :         continue;  /* at has no namespace, sorts earlier than in_at that has namespace. */
     260                 :            :     } else {
     261         [ +  + ]:     111324 :       if (at->ns)
     262                 :      17866 :         break;  /* No namespace sorts before namespace */
     263                 :            :     }
     264                 :            :     /* Neither has namespace, or namespaces were equal: sort by attribute name */
     265                 :            : 
     266         [ +  + ]:     126011 :     if (at->name) {
     267                 :     115605 :       at_name = at->name;
     268                 :     115605 :       at_name_len = at->name_len;
     269                 :     115605 :       p = memchr(at_name, ':', at_name_len);
     270         [ +  + ]:     115605 :       if (p) {
     271                 :      32273 :         at_name_len -= 1 + p - at_name;
     272                 :      32273 :         at_name = p+1;
     273                 :            :       }
     274                 :            :     } else {
     275         [ +  - ]:      10406 :       if (IN_RANGE((at->g.tok & ZX_TOK_TOK_MASK), 0, zx__ATTR_MAX)) {
     276                 :      10406 :         at_name = (char*)zx_at_tab[at->g.tok & ZX_TOK_TOK_MASK].name;
     277                 :      10406 :         at_name_len = strlen(at_name);
     278                 :            :       } else {
     279                 :          0 :         ERR("Attribute supplied without name and tok 0x%06x is out of range", at->g.tok);
     280                 :          0 :         break;
     281                 :            :       }
     282                 :            :     }
     283         [ +  + ]:     126011 :     if (in_at->name) {
     284                 :     115605 :       in_at_name = in_at->name;
     285                 :     115605 :       in_at_name_len = in_at->name_len;
     286                 :     115605 :       p = memchr(in_at_name, ':', in_at_name_len);
     287         [ +  + ]:     115605 :       if (p) {
     288                 :      32273 :         in_at_name_len -= 1 + p - in_at_name;
     289                 :      32273 :         in_at_name = p+1;
     290                 :            :       }
     291                 :            :     } else {
     292         [ +  - ]:      10406 :       if (IN_RANGE((in_at->g.tok & ZX_TOK_TOK_MASK), 0, zx__ATTR_MAX)) {
     293                 :      10406 :         in_at_name = (char*)zx_at_tab[in_at->g.tok & ZX_TOK_TOK_MASK].name;
     294                 :      10406 :         in_at_name_len = strlen(in_at_name);
     295                 :            :       } else {
     296                 :          0 :         ERR("Attribute supplied without name and tok 0x%06x is out of range", in_at->g.tok);
     297                 :          0 :         break;
     298                 :            :       }
     299                 :            :     }
     300                 :     126011 :     res = memcmp(at_name, in_at_name, MIN(at_name_len, in_at_name_len));
     301   [ +  +  +  +  :     126011 :     if (res > 0 || !res && at_name_len >= in_at_name_len)
                   +  + ]
     302                 :            :       break;
     303                 :            :   }
     304                 :     174048 :   in_at->g.n = &at->g;
     305                 :     174048 :   *atp = in_at;
     306                 :     174048 :   return in_at;
     307                 :            : }
     308                 :            : 
     309                 :            : /*() Called from dec-templ.c for CSE elimination. */
     310                 :            : 
     311                 :            : /* Called by:  zx_DEC_elem, zxenc_pubkey_enc, zxenc_symkey_enc, zxid_ac_desc, zxid_add_fed_tok2epr, zxid_ar_desc, zxid_az_soap, zxid_contact_desc, zxid_idp_sso_desc, zxid_key_desc, zxid_key_info, zxid_mk_a7n, zxid_mk_az, zxid_mk_az_cd1, zxid_mk_di_req_svc, zxid_mk_mni, zxid_mk_saml_resp, zxid_mk_xac_az, zxid_mk_xacml_resp, zxid_mk_xacml_simple_at, zxid_mni_desc, zxid_nimap_desc, zxid_org_desc, zxid_slo_desc, zxid_sp_meta, zxid_sp_sso_desc, zxid_sso_desc, zxid_wsc_prep, zxid_wsf_decor, zxid_wsp_decorate, zxsig_sign x3 */
     312                 :            : void zx_reverse_elem_lists(struct zx_elem_s* x)
     313                 :     743797 : {
     314                 :            :   struct zx_elem_s* iternode;
     315                 :            :   struct zx_attr_s* in_at;
     316                 :            :   struct zx_attr_s* at_next;
     317                 :            : 
     318                 :     743797 :   iternode = x->kids;
     319         [ +  + ]:     743797 :   REVERSE_LIST_NEXT(x->kids, iternode, g.n);
     320                 :            : 
     321                 :     743797 :   zx_chk_el_ord(x);
     322                 :            :   
     323                 :            :   /* Insertion sort attribute list in alphabetical order 1st by NS URI, then by attribute name */
     324                 :            : 
     325                 :     743797 :   in_at = x->attr;
     326   [ +  +  +  + ]:     743797 :   if (!in_at || !in_at->g.n)
     327                 :     642128 :     return;  /* Nothing to sort (no attributes or just one attribute) */
     328                 :            : 
     329                 :     101669 :   at_next = in_at;    /* Start insertion sort by considering first to already be in place. */
     330                 :     101669 :   in_at = (struct zx_attr_s*)in_at->g.n;
     331                 :     101669 :   at_next->g.n = 0;
     332                 :            : 
     333         [ +  + ]:     274423 :   for (; in_at; in_at = at_next) {
     334                 :     172754 :     at_next = (struct zx_attr_s*)in_at->g.n;
     335                 :     172754 :     zx_ord_ins_at(x, in_at);
     336                 :            :   }
     337                 :            : }
     338                 :            : 
     339                 :            : /*() Called from dec-templ.c for CSE elimination. */
     340                 :            : 
     341                 :            : /* Called by:  zx_attr_lookup */
     342                 :            : static const char* zx_dec_attr_val(struct zx_ctx* c, const char* func)
     343                 :     717120 : {
     344                 :            :   const char* data;
     345                 :            :   char quote;
     346                 :     717120 :   quote = '=';
     347         [ +  - ]:     717120 :   ZX_LOOK_FOR(c,'=');
     348                 :            :   
     349                 :     717120 :   ++c->p;
     350   [ +  +  -  + ]:     717120 :   if (!ONE_OF_2(*c->p, '"', '\'')) {
     351                 :          0 :     zx_xml_parse_err(c, *c->p, func, "zx_dec_attr_val: Did not find expected quote char (single or double), saw");
     352                 :          0 :     return 0;
     353                 :            :   }
     354                 :     717120 :   quote = *c->p;
     355                 :     717120 :   ++c->p;
     356                 :     717120 :   data = c->p;       
     357                 :            :   
     358         [ +  - ]:     717120 :   ZX_LOOK_FOR(c, quote);
     359                 :     717120 :   return data;
     360                 :          0 :  look_for_not_found:
     361                 :          0 :   zx_xml_parse_err(c, quote, func, "zx_dec_attr_val: char not found");
     362                 :          0 :   return 0;
     363                 :            : }
     364                 :            : 
     365                 :            : /*() Tokenize an attribute.
     366                 :            :  * Lookup functions to convert a namespace qualified string to an integer token.
     367                 :            :  * The att2tok() functions come from xsd2sg.pl code generation via gperf.
     368                 :            :  * Internal function CSE.
     369                 :            :  * Starts with c->p pointing to beginning of attribute (with ns prefix, if any) */
     370                 :            : 
     371                 :            : /* Called by:  zx_DEC_elem */
     372                 :            : static int zx_attr_lookup(struct zx_ctx* c, struct zx_elem_s* x)
     373                 :    1447294 : {
     374                 :            :   const char* prefix;
     375                 :            :   const char* name;
     376                 :            :   const char* lim;
     377                 :            :   const char* data;
     378                 :            :   const char* p;
     379                 :            :   struct zx_ns_s* ns;
     380                 :            :   const struct zx_at_tok* zt;
     381                 :            :   struct zx_attr_s* attr;
     382                 :            : 
     383         [ -  + ]:    1447294 :   ZX_SKIP_WS(c, ZX_TOK_ATTR_ERR);
     384   [ +  +  +  + ]:    1447294 :   if (ONE_OF_2(*c->p, '>', '/'))
     385                 :     730174 :     return ZX_TOK_NO_ATTR;
     386                 :            : 
     387                 :     717120 :   attr = ZX_ZALLOC(c, struct zx_attr_s);
     388                 :     717120 :   attr->name = (char*)(name = c->p);
     389         [ -  + ]:     717120 :   if (!(data = zx_dec_attr_val(c, "attr_lookup"))) {
     390                 :          0 :     ZX_FREE(c, attr);
     391                 :          0 :     return ZX_TOK_ATTR_ERR;
     392                 :            :   }
     393                 :     717120 :   attr->name_len = data - 2 - attr->name;
     394                 :     717120 :   attr->g.s = (char*)data;
     395                 :     717120 :   attr->g.len = c->p - attr->g.s;
     396                 :     717120 :   lim = attr->g.s - 2;
     397                 :            :   /*attr->g.tok = ZX_TOK_NS_NOT_FOUND;  / * Start with unknown namespace. */
     398                 :            : 
     399                 :     717120 :   p = memchr(name, ':', lim-name);  /* look for namespace prefix */
     400         [ +  + ]:     717120 :   if (p) {
     401                 :     326777 :     prefix = name;
     402                 :     326777 :     name = p+1;
     403                 :            :   } else
     404                 :     390343 :     prefix = 0;
     405                 :            : 
     406                 :            :   /* Look for namespace declaration. Skip as these were prescanned (see above in this file). */
     407         [ +  + ]:     717120 :   if (prefix) {
     408   [ +  +  +  - ]:     326777 :     if ((name-1)-prefix == sizeof("xmlns")-1 && !memcmp("xmlns", prefix, sizeof("xmlns")-1)) {
     409                 :     217486 :       ZX_FREE(c, attr);
     410                 :     217486 :       zx_xmlns_detected(c, x, data);
     411                 :     217486 :       return ZX_TOK_XMLNS;
     412                 :            :     }
     413                 :     109291 :     ns = zx_prefix_seen_whine(c, (name-1)-prefix, prefix, "attr_lookup", 0);
     414         [ +  - ]:     109291 :     if (ns) {
     415                 :     109291 :       attr->ns = ns;
     416         [ +  + ]:     109291 :       if (ns->master)
     417                 :     108358 :         ns = ns->master;
     418   [ +  -  +  - ]:     218582 :       if (ns > c->ns_tab && ns - c->ns_tab < c->n_ns) {
     419                 :     109291 :         attr->g.tok = (ns - c->ns_tab) << ZX_TOK_NS_SHIFT;
     420                 :            :       } else {
     421                 :          0 :         INFO("Non-native prefix(%.*s) attr(%.*s) in elem(%.*s)", (name-1)-prefix, prefix, attr->name_len, attr->name, x->g.len, x->g.s);
     422                 :            :       }
     423                 :            :     } else {
     424                 :          0 :       INFO("Undeclared (and unknown) prefix(%.*s) attr(%.*s) in elem(%.*s)", (name-1)-prefix, prefix, attr->name_len, attr->name, x->g.len, x->g.s);
     425                 :            :     }
     426                 :            :   } else {
     427   [ +  +  +  + ]:     390343 :     if (lim-name == sizeof("xmlns")-1 && !memcmp("xmlns", name, sizeof("xmlns")-1)) {
     428                 :       2017 :       ZX_FREE(c, attr);
     429                 :       2017 :       zx_xmlns_detected(c, x, data);
     430                 :       2017 :       return ZX_TOK_XMLNS;
     431                 :            :     }
     432                 :            :     /* Most attributes are namespaceless (or have containing element's namespace). */
     433                 :            :   }
     434                 :            :   
     435                 :     497617 :   attr->g.n = &x->attr->g;
     436                 :     497617 :   x->attr = attr;
     437                 :     497617 :   zt = zx_attr2tok(name, lim-name);
     438         [ +  + ]:     497617 :   if (zt)
     439                 :     497557 :     return attr->g.tok |= (zt - zx_at_tab);
     440                 :         60 :   return attr->g.tok |= ZX_TOK_ATTR_NOT_FOUND;
     441                 :            : }
     442                 :            : 
     443                 :            : /*() Given token, find element descriptor. */
     444                 :            : 
     445                 :            : /* Called by:  zx_DEC_elem, zx_ENC_WO_any_elem, zx_LEN_WO_any_elem, zx_chk_el_ord, zx_el_lookup, zx_new_elem */
     446                 :            : struct zx_el_desc* zx_el_desc_lookup(int tok)
     447                 :    2289966 : {
     448                 :            :   struct zx_el_desc* ed;
     449         [ +  + ]:    2289966 :   if (tok == ZX_TOK_NOT_FOUND)
     450                 :      25100 :     return 0;
     451         [ -  + ]:    2264866 :   if (!IN_RANGE(tok & ZX_TOK_TOK_MASK, 0, zx__ELEM_MAX)) {
     452                 :          0 :     ERR("out of range token 0x%06x", tok);
     453                 :          0 :     return 0;
     454                 :            :   }
     455         [ +  + ]:    3465530 :   for (ed = zx_el_tab[tok & ZX_TOK_TOK_MASK].n; ed; ed = ed->n)
     456         [ +  + ]:    3461634 :     if (ed->tok == tok)
     457                 :    2260970 :       return ed;
     458                 :       3896 :   ERR("unknown token 0x%06x", tok);
     459                 :       3896 :   return 0;
     460                 :            : }
     461                 :            : 
     462                 :            : /*() Lookup function to convert a namespace qualified string to an integer token.
     463                 :            :  * First namespace is looked up and then the element in namespace specific hash.
     464                 :            :  * The hash functions come from xsd2sg.pl code generation via gperf. */
     465                 :            : 
     466                 :            : /* Called by:  zx_DEC_elem */
     467                 :            : static struct zx_elem_s* zx_el_lookup(struct zx_ctx* c, struct zx_elem_s* x, struct zx_ns_s** pop_seenp)
     468                 :     730174 : {
     469                 :            :   struct zx_elem_s* el;
     470                 :            :   struct zx_ns_s* ns;
     471                 :            :   struct zx_ns_s* master_ns;
     472                 :            :   const struct zx_el_tok* zt;
     473                 :            :   const struct zx_el_desc* ed;
     474                 :            :   const char* full_name;
     475                 :            :   const char* name;
     476                 :            :   const char* prefix;
     477                 :            :   const char* p;
     478                 :            :   int tok;
     479                 :            : 
     480         [ -  + ]:     730174 :   if (!(name = zx_scan_elem_start(c, (const char*)__FUNCTION__)))
     481                 :          0 :     return 0;
     482                 :            :   
     483                 :     730174 :   *pop_seenp = zx_scan_xmlns(c);    /* Prescan namespaces so token can be correctly recognized. */
     484                 :            : 
     485                 :     730174 :   full_name = name;
     486                 :     730174 :   p = memchr(name, ':', c->p-name); /* look for namespace prefix */
     487         [ +  + ]:     730174 :   if (p) {
     488                 :     720334 :     prefix = name;
     489                 :     720334 :     name = p+1;
     490                 :            :   } else
     491                 :       9840 :     prefix = 0;
     492                 :            : 
     493         [ +  + ]:     730174 :   ns = zx_prefix_seen_whine(c, prefix ? (name-1)-prefix : 0, prefix, (const char*)__FUNCTION__,1);
     494         [ +  + ]:     730174 :   master_ns = ns->master?ns->master:ns;
     495                 :     730174 :   zt = zx_elem2tok(name, c->p - name);
     496         [ +  + ]:     730174 :   if (zt) {
     497                 :     721514 :     tok = ((master_ns - c->ns_tab) << ZX_TOK_NS_SHIFT) | (zt - zx_el_tab);
     498                 :     721514 :     ed = zx_el_desc_lookup(tok);
     499         [ +  + ]:     721514 :     if (ed) {
     500                 :     717618 :       el = ZX_ALLOC(c, ed->siz);
     501                 :     717618 :       ZERO(el, ed->siz);
     502                 :            :     } else
     503                 :       3896 :       goto unknown_el;
     504                 :            :   } else {
     505                 :      12556 : unknown_el:
     506                 :      12556 :     INFO("Unknown element <%.*s>, child of <%.*s>", c->p - full_name, full_name, x->g.len, x->g.s);
     507                 :      12556 :     el = ZX_ZALLOC(c, struct zx_elem_s);
     508                 :      12556 :     tok = ZX_TOK_NOT_FOUND;
     509                 :            :   }
     510                 :            : 
     511                 :     730174 :   el->g.tok = tok;
     512                 :     730174 :   el->ns = ns;
     513                 :     730174 :   el->g.s = (char*)full_name;
     514                 :     730174 :   el->g.len = c->p - full_name;
     515                 :     730174 :   el->g.n = &x->kids->g;
     516                 :     730174 :   x->kids = el;
     517                 :     730174 :   return el;
     518                 :            : }
     519                 :            : 
     520                 :            : /*() Element Decoder. When per element decoder is called, the c->p
     521                 :            :  * will point to just past the element name. The element has already
     522                 :            :  * been allocated to the correct size and the namespace prescan has
     523                 :            :  * already been done. */
     524                 :            : 
     525                 :            : /* Called by:  zx_DEC_elem, zx_dec_zx_root */
     526                 :            : void zx_DEC_elem(struct zx_ctx* c, struct zx_elem_s* x)
     527                 :     751015 : {
     528                 :            :   int tok MAYBE_UNUSED;  /* Unused in zx_DEC_root() */
     529                 :     751015 :   struct zx_el_desc* ed = zx_el_desc_lookup(x->g.tok);
     530                 :            :   struct zx_elem_s* el;
     531                 :            :   struct zx_ns_s* pop_seen;
     532                 :            : 
     533         [ +  + ]:     751015 :   if (x->g.tok != zx_root_ELEM) {
     534                 :            :     /* The tag name has already been detected. Process attributes until '>' */
     535                 :            :     
     536         [ +  - ]:    1447294 :     for (; c->p; ++c->p) {
     537                 :    1447294 :       tok = zx_attr_lookup(c, x);
     538   [ +  +  -  +  :    1447294 :       switch (tok) {
                      + ]
     539                 :     219503 :       case ZX_TOK_XMLNS: break;
     540                 :         60 :       case ZX_TOK_ATTR_NOT_FOUND: break;
     541                 :          0 :       case ZX_TOK_ATTR_ERR: return; 
     542                 :     730174 :       case ZX_TOK_NO_ATTR: goto no_attr;
     543                 :            :       default:
     544   [ +  +  +  + ]:     497557 :         if (!ed || !ed->at_dec(c, x)) { /* element specific attribute processing */
     545   [ +  +  -  + ]:        310 :           D("Known attribute(%.*s) tok=0x%x in wrong context(%.*s)", x->attr->name_len, x->attr->name, x->attr->g.tok, x->g.len, x->g.s);
     546                 :            :         }
     547                 :            :       }
     548                 :            :     }
     549                 :     730174 : no_attr:
     550         [ +  - ]:     730174 :     if (c->p) {
     551                 :     730174 :       ++c->p;
     552   [ +  +  +  - ]:     730174 :       if (c->p[-1] == '/' && c->p[0] == '>') {  /* <Tag/> without content */
     553                 :      18303 :         ++c->p;
     554                 :      18303 :         goto out;
     555                 :            :       }
     556                 :            :     }
     557                 :            :   }
     558                 :            : 
     559                 :            :   /* Process contents until '</' */
     560                 :            :   
     561         [ +  - ]:     732712 :   while (c->p) {
     562                 :    1462928 :   next_elem:
     563                 :            :     /*ZX_SKIP_WS(c,x);    DO NOT SQUASH WS! EXC-CANON NEEDS IT. */
     564         [ +  + ]:    1462928 :     if (*c->p == '<') {
     565                 :    1442087 :     potential_tag:
     566                 :    1442087 :       ++c->p;
     567      [ +  +  + ]:    1442087 :       switch (*c->p) {
     568                 :            :       case '?':  /* processing instruction <?xml ... ?> */
     569                 :            :       case '!':  /* comment <!-- ... --> */
     570         [ +  - ]:         42 :         if (zx_scan_pi_or_comment(c))
     571                 :          0 :           break;
     572                 :         42 :         goto next_elem;
     573                 :            :       case '/':  /* close tag */
     574         [ +  + ]:     711871 :         if (!zx_scan_elem_end(c, ((struct zx_elem_s*)x)->g.s, (const char*)__FUNCTION__))
     575                 :         12 :           return;
     576                 :            :         /* Legitimate close tag. Normal exit from this function. */
     577                 :     711859 :         ++c->p;
     578                 :     711859 :         goto out;
     579                 :            :       default:
     580   [ +  -  +  -  :     730174 :         if (AZaz_(*c->p)) {
          +  +  +  -  +  
                      - ]
     581                 :     730174 :           el = zx_el_lookup(c, (struct zx_elem_s*)x, &pop_seen);
     582         [ -  + ]:     730174 :           if (!el)
     583                 :          0 :             return;
     584                 :     730174 :           zx_DEC_elem(c, el);
     585   [ +  +  +  + ]:     730174 :           if (!ed || !ed->el_dec(c, x)) { /* element specific subelement processing */
     586         [ +  + ]:      14931 :             if (el->g.tok != ZX_TOK_NOT_FOUND) {
     587   [ +  +  -  + ]:       2375 :               D("Known element(%.*s) tok=0x%x in wrong context(%.*s)", el->g.len, el->g.s, el->g.tok, x->g.len, x->g.s);
     588                 :       2375 :               el->g.tok = ZX_TOK_NOT_FOUND;
     589                 :            :             }
     590                 :            :           }
     591                 :     730174 :           zx_pop_seen(pop_seen);
     592                 :     730174 :           goto next_elem;
     593                 :            :         }
     594                 :            :       }
     595                 :            :       /* false alarm <, fall thru */
     596                 :            :     }
     597         [ +  + ]:     209730 :     if (!zx_scan_data(c, (struct zx_elem_s*)x))
     598                 :      20841 :       return;
     599                 :     188889 :     goto potential_tag;
     600                 :            :   }
     601                 :     730162 :  out:
     602                 :     730162 :   zx_reverse_elem_lists((struct zx_elem_s*)x);
     603                 :            : }
     604                 :            : 
     605                 :            : /*() Prepare a context for decoding XML. The decoding operation will not
     606                 :            :  * alter the underlying data (e.g. no nuls are inserted, not even temporarily).
     607                 :            :  * N.B. Often you would wrap this in locks, like
     608                 :            :  *   LOCK(cf->ctx->mx, "valid");
     609                 :            :  *   zx_prepare_dec_ctx(cf->ctx, zx_ns_tab, n_ns, ss->s, ss->s + ss->len);
     610                 :            :  *   r = zx_DEC_root(cf->ctx, 0, 1);
     611                 :            :  *   UNLOCK(cf->ctx->mx, "valid");
     612                 :            :  */
     613                 :            : 
     614                 :            : /* Called by:  covimp_test, zx_dec_zx_root */
     615                 :            : void zx_prepare_dec_ctx(struct zx_ctx* c, struct zx_ns_s* ns_tab, int n_ns, const char* start, const char* lim)
     616                 :      20842 : {
     617                 :      20842 :   c->guard_seen_n.seen_n = &c->guard_seen_p;
     618                 :      20842 :   c->guard_seen_p.seen_p = &c->guard_seen_n;
     619                 :      20842 :   c->ns_tab = ns_tab;
     620                 :      20842 :   c->n_ns = n_ns;
     621                 :      20842 :   c->bas = c->p = start;
     622                 :      20842 :   c->lim = lim;
     623                 :      20842 : }
     624                 :            : 
     625                 :            : /*(i) Decode arbitary xml with zx_ns_tab set of namespaces and parsers. */
     626                 :            : 
     627                 :            : /* Called by:  main x8, sig_validate, test_ibm_cert_problem, zxid_add_env_if_needed x2, zxid_dec_a7n, zxid_decode_redir_or_post, zxid_decrypt_nameid, zxid_decrypt_newnym, zxid_di_query, zxid_find_epr, zxid_gen_boots, zxid_get_ses_sso_a7n x2, zxid_idp_soap_parse, zxid_parse_meta, zxid_print_session, zxid_reg_svc, zxid_soap_call_raw, zxid_sp_soap_parse, zxid_str2a7n, zxid_str2nid, zxid_str2token, zxid_wsp_validate */
     628                 :            : struct zx_root_s* zx_dec_zx_root(struct zx_ctx* c, int len, const char* start, const char* func)
     629                 :      20841 : {
     630                 :      20841 :   struct zx_root_s* r = zx_NEW_root(c, 0);
     631   [ -  +  #  # ]:      20841 :   LOCK(c->mx, func);
     632                 :      20841 :   zx_prepare_dec_ctx(c, zx_ns_tab, sizeof(zx_ns_tab)/sizeof(struct zx_ns_s), start, start + len);
     633                 :      20841 :   zx_DEC_elem(c, &r->gg);
     634   [ -  +  #  # ]:      20841 :   UNLOCK(c->mx, func);
     635                 :      20841 :   return r;
     636                 :            : }
     637                 :            : 
     638                 :            : /* EOF -- zxlibdec.c */

Generated by: LCOV version 1.9