UA_readNumberWithBase:
  110|    560|UA_readNumberWithBase(const UA_Byte *buf, size_t buflen, UA_UInt32 *number, UA_Byte base) {
  111|    560|    UA_assert(buf);
  ------------------
  |  |  411|    560|# define UA_assert(ignore) assert(ignore)
  ------------------
  |  Branch (111:5): [True: 560, False: 0]
  ------------------
  112|    560|    UA_assert(number);
  ------------------
  |  |  411|    560|# define UA_assert(ignore) assert(ignore)
  ------------------
  |  Branch (112:5): [True: 560, False: 0]
  ------------------
  113|    560|    u32 n = 0;
  114|    560|    size_t progress = 0;
  115|       |    /* read numbers until the end or a non-number character appears */
  116|  6.46M|    while(progress < buflen) {
  ------------------
  |  Branch (116:11): [True: 6.46M, False: 268]
  ------------------
  117|  6.46M|        u8 c = buf[progress];
  118|  6.46M|        if(c >= '0' && c <= '9' && c <= '0' + (base-1))
  ------------------
  |  Branch (118:12): [True: 6.46M, False: 178]
  |  Branch (118:24): [True: 6.46M, False: 114]
  |  Branch (118:36): [True: 6.46M, False: 0]
  ------------------
  119|  6.46M|           n = (n * base) + c - '0';
  120|    292|        else if(base > 9 && c >= 'a' && c <= 'z' && c <= 'a' + (base-11))
  ------------------
  |  Branch (120:17): [True: 292, False: 0]
  |  Branch (120:29): [True: 70, False: 222]
  |  Branch (120:41): [True: 22, False: 48]
  |  Branch (120:53): [True: 0, False: 22]
  ------------------
  121|      0|           n = (n * base) + c-'a' + 10;
  122|    292|        else if(base > 9 && c >= 'A' && c <= 'Z' && c <= 'A' + (base-11))
  ------------------
  |  Branch (122:17): [True: 292, False: 0]
  |  Branch (122:29): [True: 85, False: 207]
  |  Branch (122:41): [True: 10, False: 75]
  |  Branch (122:53): [True: 0, False: 10]
  ------------------
  123|      0|           n = (n * base) + c-'A' + 10;
  124|    292|        else
  125|    292|           break;
  126|  6.46M|        ++progress;
  127|  6.46M|    }
  128|    560|    *number = n;
  129|    560|    return progress;
  130|    560|}
UA_readNumber:
  133|    560|UA_readNumber(const UA_Byte *buf, size_t buflen, UA_UInt32 *number) {
  134|    560|    return UA_readNumberWithBase(buf, buflen, number, 10);
  135|    560|}
UA_parseEndpointUrl:
  146|    520|                    UA_UInt16 *outPort, UA_String *outPath) {
  147|       |    /* Url must begin with "opc.tcp://" or opc.udp:// (if pubsub enabled) */
  148|    520|    if(endpointUrl->length < 11) {
  ------------------
  |  Branch (148:8): [True: 7, False: 513]
  ------------------
  149|      7|        return UA_STATUSCODE_BADTCPENDPOINTURLINVALID;
  ------------------
  |  |  499|      7|#define UA_STATUSCODE_BADTCPENDPOINTURLINVALID ((UA_StatusCode) 0x80830000)
  ------------------
  150|      7|    }
  151|       |
  152|       |    /* Which type of schema is this? */
  153|    513|    unsigned schemaType = 0;
  154|  1.36k|    for(; schemaType < UA_SCHEMAS_SIZE; schemaType++) {
  ------------------
  |  |  137|  1.36k|#define UA_SCHEMAS_SIZE 4
  ------------------
  |  Branch (154:11): [True: 1.26k, False: 98]
  ------------------
  155|  1.26k|        if(strncmp((char*)endpointUrl->data,
  ------------------
  |  Branch (155:12): [True: 415, False: 850]
  ------------------
  156|  1.26k|                   schemas[schemaType],
  157|  1.26k|                   strlen(schemas[schemaType])) == 0)
  158|    415|            break;
  159|  1.26k|    }
  160|    513|    if(schemaType == UA_SCHEMAS_SIZE)
  ------------------
  |  |  137|    513|#define UA_SCHEMAS_SIZE 4
  ------------------
  |  Branch (160:8): [True: 98, False: 415]
  ------------------
  161|     98|        return UA_STATUSCODE_BADTCPENDPOINTURLINVALID;
  ------------------
  |  |  499|     98|#define UA_STATUSCODE_BADTCPENDPOINTURLINVALID ((UA_StatusCode) 0x80830000)
  ------------------
  162|       |
  163|       |    /* Forward the current position until the first colon or slash */
  164|    415|    size_t start = strlen(schemas[schemaType]);
  165|    415|    size_t curr = start;
  166|    415|    UA_Boolean ipv6 = false;
  167|    415|    if(endpointUrl->length > curr && endpointUrl->data[curr] == '[') {
  ------------------
  |  Branch (167:8): [True: 414, False: 1]
  |  Branch (167:38): [True: 127, False: 287]
  ------------------
  168|       |        /* IPv6: opc.tcp://[2001:0db8:85a3::8a2e:0370:7334]:1234/path */
  169|  9.12M|        for(; curr < endpointUrl->length; ++curr) {
  ------------------
  |  Branch (169:15): [True: 9.12M, False: 21]
  ------------------
  170|  9.12M|            if(endpointUrl->data[curr] == ']')
  ------------------
  |  Branch (170:16): [True: 106, False: 9.12M]
  ------------------
  171|    106|                break;
  172|  9.12M|        }
  173|    127|        if(curr == endpointUrl->length)
  ------------------
  |  Branch (173:12): [True: 21, False: 106]
  ------------------
  174|     21|            return UA_STATUSCODE_BADTCPENDPOINTURLINVALID;
  ------------------
  |  |  499|     21|#define UA_STATUSCODE_BADTCPENDPOINTURLINVALID ((UA_StatusCode) 0x80830000)
  ------------------
  175|    106|        curr++;
  176|    106|        ipv6 = true;
  177|    288|    } else {
  178|       |        /* IPv4 or hostname: opc.tcp://something.something:1234/path */
  179|  1.11M|        for(; curr < endpointUrl->length; ++curr) {
  ------------------
  |  Branch (179:15): [True: 1.11M, False: 52]
  ------------------
  180|  1.11M|            if(endpointUrl->data[curr] == ':' || endpointUrl->data[curr] == '/')
  ------------------
  |  Branch (180:16): [True: 185, False: 1.11M]
  |  Branch (180:50): [True: 51, False: 1.11M]
  ------------------
  181|    236|                break;
  182|  1.11M|        }
  183|    288|    }
  184|       |
  185|       |    /* Set the hostname */
  186|    394|    if(ipv6) {
  ------------------
  |  Branch (186:8): [True: 106, False: 288]
  ------------------
  187|       |        /* Skip the ipv6 '[]' container for getaddrinfo() later */
  188|    106|        outHostname->data = &endpointUrl->data[start+1];
  189|    106|        outHostname->length = curr - (start+2);
  190|    288|    } else {
  191|    288|        outHostname->data = &endpointUrl->data[start];
  192|    288|        outHostname->length = curr - start;
  193|    288|    }
  194|       |
  195|       |    /* Empty string? */
  196|    394|    if(outHostname->length == 0)
  ------------------
  |  Branch (196:8): [True: 218, False: 176]
  ------------------
  197|    218|        outHostname->data = NULL;
  198|       |
  199|       |    /* Already at the end */
  200|    394|    if(curr == endpointUrl->length)
  ------------------
  |  Branch (200:8): [True: 95, False: 299]
  ------------------
  201|     95|        return UA_STATUSCODE_GOOD;
  ------------------
  |  |   16|     95|#define UA_STATUSCODE_GOOD ((UA_StatusCode) 0x00000000)
  ------------------
  202|       |
  203|       |    /* Set the port - and for ETH set the VID.PCP postfix in the outpath string.
  204|       |     * We have to parse that externally. */
  205|    299|    if(endpointUrl->data[curr] == ':') {
  ------------------
  |  Branch (205:8): [True: 215, False: 84]
  ------------------
  206|    215|        if(++curr == endpointUrl->length)
  ------------------
  |  Branch (206:12): [True: 2, False: 213]
  ------------------
  207|      2|            return UA_STATUSCODE_BADTCPENDPOINTURLINVALID;
  ------------------
  |  |  499|      2|#define UA_STATUSCODE_BADTCPENDPOINTURLINVALID ((UA_StatusCode) 0x80830000)
  ------------------
  208|       |
  209|       |        /* ETH schema */
  210|    213|        if(schemaType == UA_ETH_SCHEMA_INDEX) {
  ------------------
  |  |  138|    213|#define UA_ETH_SCHEMA_INDEX 2
  ------------------
  |  Branch (210:12): [True: 1, False: 212]
  ------------------
  211|      1|            if(outPath != NULL) {
  ------------------
  |  Branch (211:16): [True: 1, False: 0]
  ------------------
  212|      1|                outPath->data = &endpointUrl->data[curr];
  213|      1|                outPath->length = endpointUrl->length - curr;
  214|      1|            }
  215|      1|            return UA_STATUSCODE_GOOD;
  ------------------
  |  |   16|      1|#define UA_STATUSCODE_GOOD ((UA_StatusCode) 0x00000000)
  ------------------
  216|      1|        }
  217|       |
  218|    212|        u32 largeNum;
  219|    212|        size_t progress = UA_readNumber(&endpointUrl->data[curr],
  220|    212|                                        endpointUrl->length - curr, &largeNum);
  221|    212|        if(progress == 0 || largeNum > 65535)
  ------------------
  |  Branch (221:12): [True: 52, False: 160]
  |  Branch (221:29): [True: 49, False: 111]
  ------------------
  222|    101|            return UA_STATUSCODE_BADTCPENDPOINTURLINVALID;
  ------------------
  |  |  499|    101|#define UA_STATUSCODE_BADTCPENDPOINTURLINVALID ((UA_StatusCode) 0x80830000)
  ------------------
  223|       |        /* Test if the end of a valid port was reached */
  224|    111|        curr += progress;
  225|    111|        if(curr == endpointUrl->length || endpointUrl->data[curr] == '/')
  ------------------
  |  Branch (225:12): [True: 57, False: 54]
  |  Branch (225:43): [True: 16, False: 38]
  ------------------
  226|     73|            *outPort = (u16)largeNum;
  227|    111|        if(curr == endpointUrl->length)
  ------------------
  |  Branch (227:12): [True: 57, False: 54]
  ------------------
  228|     57|            return UA_STATUSCODE_GOOD;
  ------------------
  |  |   16|     57|#define UA_STATUSCODE_GOOD ((UA_StatusCode) 0x00000000)
  ------------------
  229|    111|    }
  230|       |
  231|       |    /* Set the path */
  232|    138|    UA_assert(curr < endpointUrl->length);
  ------------------
  |  |  411|    138|# define UA_assert(ignore) assert(ignore)
  ------------------
  |  Branch (232:5): [True: 138, False: 0]
  ------------------
  233|    138|    if(endpointUrl->data[curr] != '/')
  ------------------
  |  Branch (233:8): [True: 68, False: 70]
  ------------------
  234|     68|        return UA_STATUSCODE_BADTCPENDPOINTURLINVALID;
  ------------------
  |  |  499|     68|#define UA_STATUSCODE_BADTCPENDPOINTURLINVALID ((UA_StatusCode) 0x80830000)
  ------------------
  235|     70|    if(++curr == endpointUrl->length)
  ------------------
  |  Branch (235:8): [True: 9, False: 61]
  ------------------
  236|      9|        return UA_STATUSCODE_GOOD;
  ------------------
  |  |   16|      9|#define UA_STATUSCODE_GOOD ((UA_StatusCode) 0x00000000)
  ------------------
  237|     61|    if(outPath != NULL) {
  ------------------
  |  Branch (237:8): [True: 61, False: 0]
  ------------------
  238|     61|        outPath->data = &endpointUrl->data[curr];
  239|     61|        outPath->length = endpointUrl->length - curr;
  240|       |
  241|       |        /* Remove trailing slash from the path */
  242|     61|        if(endpointUrl->data[endpointUrl->length - 1] == '/')
  ------------------
  |  Branch (242:12): [True: 11, False: 50]
  ------------------
  243|     11|            outPath->length--;
  244|       |
  245|       |        /* Empty string? */
  246|     61|        if(outPath->length == 0)
  ------------------
  |  Branch (246:12): [True: 10, False: 51]
  ------------------
  247|     10|            outPath->data = NULL;
  248|     61|    }
  249|       |
  250|     61|    return UA_STATUSCODE_GOOD;
  ------------------
  |  |   16|     61|#define UA_STATUSCODE_GOOD ((UA_StatusCode) 0x00000000)
  ------------------
  251|     70|}
UA_parseEndpointUrlEthernet:
  255|    366|                            UA_UInt16 *vid, UA_Byte *pcp) {
  256|       |    /* Url must begin with "opc.eth://" */
  257|    366|    if(endpointUrl->length < 11) {
  ------------------
  |  Branch (257:8): [True: 6, False: 360]
  ------------------
  258|      6|        return UA_STATUSCODE_BADINTERNALERROR;
  ------------------
  |  |   28|      6|#define UA_STATUSCODE_BADINTERNALERROR ((UA_StatusCode) 0x80020000)
  ------------------
  259|      6|    }
  260|    360|    if(strncmp((char*) endpointUrl->data, "opc.eth://", 10) != 0) {
  ------------------
  |  Branch (260:8): [True: 88, False: 272]
  ------------------
  261|     88|        return UA_STATUSCODE_BADINTERNALERROR;
  ------------------
  |  |   28|     88|#define UA_STATUSCODE_BADINTERNALERROR ((UA_StatusCode) 0x80020000)
  ------------------
  262|     88|    }
  263|       |
  264|       |    /* Where does the host address end? */
  265|    272|    size_t curr = 10;
  266|  1.10M|    for(; curr < endpointUrl->length; ++curr) {
  ------------------
  |  Branch (266:11): [True: 1.10M, False: 19]
  ------------------
  267|  1.10M|        if(endpointUrl->data[curr] == ':') {
  ------------------
  |  Branch (267:12): [True: 253, False: 1.10M]
  ------------------
  268|    253|           break;
  269|    253|        }
  270|  1.10M|    }
  271|       |
  272|       |    /* set host address */
  273|    272|    target->data = &endpointUrl->data[10];
  274|    272|    target->length = curr - 10;
  275|    272|    if(curr == endpointUrl->length) {
  ------------------
  |  Branch (275:8): [True: 19, False: 253]
  ------------------
  276|     19|        return UA_STATUSCODE_GOOD;
  ------------------
  |  |   16|     19|#define UA_STATUSCODE_GOOD ((UA_StatusCode) 0x00000000)
  ------------------
  277|     19|    }
  278|       |
  279|       |    /* Set VLAN */
  280|    253|    u32 value = 0;
  281|    253|    curr++;  /* skip ':' */
  282|    253|    size_t progress = UA_readNumber(&endpointUrl->data[curr],
  283|    253|                                    endpointUrl->length - curr, &value);
  284|    253|    if(progress == 0 || value > 4096) {
  ------------------
  |  Branch (284:8): [True: 30, False: 223]
  |  Branch (284:25): [True: 60, False: 163]
  ------------------
  285|     90|        return UA_STATUSCODE_BADINTERNALERROR;
  ------------------
  |  |   28|     90|#define UA_STATUSCODE_BADINTERNALERROR ((UA_StatusCode) 0x80020000)
  ------------------
  286|     90|    }
  287|    163|    curr += progress;
  288|    163|    if(curr == endpointUrl->length || endpointUrl->data[curr] == '.') {
  ------------------
  |  Branch (288:8): [True: 33, False: 130]
  |  Branch (288:39): [True: 95, False: 35]
  ------------------
  289|    128|        *vid = (UA_UInt16) value;
  290|    128|    }
  291|    163|    if(curr == endpointUrl->length) {
  ------------------
  |  Branch (291:8): [True: 33, False: 130]
  ------------------
  292|     33|        return UA_STATUSCODE_GOOD;
  ------------------
  |  |   16|     33|#define UA_STATUSCODE_GOOD ((UA_StatusCode) 0x00000000)
  ------------------
  293|     33|    }
  294|       |
  295|       |    /* Set priority */
  296|    130|    if(endpointUrl->data[curr] != '.') {
  ------------------
  |  Branch (296:8): [True: 35, False: 95]
  ------------------
  297|     35|        return UA_STATUSCODE_BADINTERNALERROR;
  ------------------
  |  |   28|     35|#define UA_STATUSCODE_BADINTERNALERROR ((UA_StatusCode) 0x80020000)
  ------------------
  298|     35|    }
  299|     95|    curr++;  /* skip '.' */
  300|     95|    progress = UA_readNumber(&endpointUrl->data[curr],
  301|     95|                             endpointUrl->length - curr, &value);
  302|     95|    if(progress == 0 || value > 7) {
  ------------------
  |  Branch (302:8): [True: 7, False: 88]
  |  Branch (302:25): [True: 60, False: 28]
  ------------------
  303|     67|        return UA_STATUSCODE_BADINTERNALERROR;
  ------------------
  |  |   28|     67|#define UA_STATUSCODE_BADINTERNALERROR ((UA_StatusCode) 0x80020000)
  ------------------
  304|     67|    }
  305|     28|    curr += progress;
  306|     28|    if(curr != endpointUrl->length) {
  ------------------
  |  Branch (306:8): [True: 24, False: 4]
  ------------------
  307|     24|        return UA_STATUSCODE_BADINTERNALERROR;
  ------------------
  |  |   28|     24|#define UA_STATUSCODE_BADINTERNALERROR ((UA_StatusCode) 0x80020000)
  ------------------
  308|     24|    }
  309|      4|    *pcp = (UA_Byte) value;
  310|       |
  311|      4|    return UA_STATUSCODE_GOOD;
  ------------------
  |  |   16|      4|#define UA_STATUSCODE_GOOD ((UA_StatusCode) 0x00000000)
  ------------------
  312|     28|}

UA_memoryManager_setLimitFromLast4Bytes:
  156|    893|int UA_memoryManager_setLimitFromLast4Bytes(const uint8_t *data, size_t size) {
  157|    893|    UA_mallocSingleton = UA_memoryManager_malloc;
  158|    893|    UA_freeSingleton = UA_memoryManager_free;
  159|    893|    UA_callocSingleton = UA_memoryManager_calloc;
  160|    893|    UA_reallocSingleton = UA_memoryManager_realloc;
  161|    893|    if(size <4)
  ------------------
  |  Branch (161:8): [True: 2, False: 891]
  ------------------
  162|      2|        return 0;
  163|       |    // just cast the last 4 bytes to uint32
  164|    891|    const uint32_t *newLimit = (const uint32_t*)(uintptr_t)&(data[size-4]);
  165|    891|    uint32_t limit;
  166|       |    // use memcopy to avoid asan complaining on misaligned memory
  167|    891|    memcpy(&limit, newLimit, sizeof(uint32_t));
  168|    891|    memoryLimit = limit;
  169|    891|    return 1;
  170|    893|}

LLVMFuzzerTestOneInput:
   42|    893|extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
   43|       |
   44|    893|    if (!UA_memoryManager_setLimitFromLast4Bytes(data, size))
  ------------------
  |  Branch (44:9): [True: 2, False: 891]
  ------------------
   45|      2|        return 0;
   46|    891|    size -= 4;
   47|       |
   48|    891|    if (size == 0)
  ------------------
  |  Branch (48:9): [True: 1, False: 890]
  ------------------
   49|      1|        return 0;
   50|       |
   51|       |    // use first byte to decide which function should be fuzzed
   52|       |
   53|    890|    const uint8_t select = data[0];
   54|       |
   55|    890|    const uint8_t *newData = &data[1];
   56|    890|    size_t  newSize = size-1;
   57|       |
   58|    890|    switch(select) {
   59|    520|        case 0:
  ------------------
  |  Branch (59:9): [True: 520, False: 370]
  ------------------
   60|    520|            return tortureParseEndpointUrl(newData, newSize);
   61|    366|        case 1:
  ------------------
  |  Branch (61:9): [True: 366, False: 524]
  ------------------
   62|    366|            return tortureParseEndpointUrlEthernet(newData, newSize);
   63|      4|        default:
  ------------------
  |  Branch (63:9): [True: 4, False: 886]
  ------------------
   64|      4|            return 0;
   65|    890|    }
   66|       |
   67|    890|}
fuzz_src_ua_util.cc:_ZL23tortureParseEndpointUrlPKhm:
   14|    520|static int tortureParseEndpointUrl(const uint8_t *data, size_t size) {
   15|    520|    const UA_String endpointUrl = {
   16|    520|        size, (UA_Byte* )(void*)data
   17|    520|    };
   18|       |
   19|    520|    UA_String hostname;
   20|    520|    UA_UInt16 port;
   21|    520|    UA_String path;
   22|    520|    UA_parseEndpointUrl(&endpointUrl, &hostname, &port, &path);
   23|    520|    return 0;
   24|    520|}
fuzz_src_ua_util.cc:_ZL31tortureParseEndpointUrlEthernetPKhm:
   26|    366|static int tortureParseEndpointUrlEthernet(const uint8_t *data, size_t size) {
   27|    366|    const UA_String endpointUrl = {
   28|    366|        size, (UA_Byte* )(void*)data
   29|    366|    };
   30|       |
   31|    366|    UA_String target;
   32|    366|    UA_UInt16 vid;
   33|    366|    UA_Byte prid;
   34|    366|    UA_parseEndpointUrlEthernet(&endpointUrl, &target, &vid, &prid);
   35|    366|    return 0;
   36|    366|}

