client:
   47|      1|void *client(void *args){ 
   48|       |
   49|      1|    Fuzzer *fuzzer = (Fuzzer*)args;
   50|      1|    int sockfd;
   51|      1|    struct sockaddr_in serv_addr;
   52|       |
   53|      1|    sockfd = socket(AF_INET, SOCK_STREAM, 0);
   54|      1|    serv_addr.sin_family = AF_INET;
   55|      1|    serv_addr.sin_port = htons(fuzzer->port);
   56|      1|    serv_addr.sin_addr.s_addr = inet_addr("127.0.0.1");
   57|       |
   58|      1|    while(1){/* Try until connect*/
  ------------------
  |  Branch (58:11): [Folded - Ignored]
  ------------------
   59|      1|        if (connect(sockfd, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) < 0){
  ------------------
  |  Branch (59:13): [True: 0, False: 1]
  ------------------
   60|      0|            continue;
   61|      1|        }else{
   62|      1|            break;
   63|      1|        }
   64|      1|    }
   65|       |
   66|      1|    send(sockfd,fuzzer->buffer,fuzzer->size,0);
   67|       |
   68|      1|    close(sockfd);
   69|      1|    pthread_exit(NULL);
   70|      1|}
LLVMFuzzerTestOneInput:
   72|     46|extern int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
   73|       |
   74|     46|    if (size < kMinInputLength || size > kMaxInputLength){
  ------------------
  |  |   29|     92|#define kMinInputLength 9
  ------------------
                  if (size < kMinInputLength || size > kMaxInputLength){
  ------------------
  |  |   30|     41|#define kMaxInputLength MODBUS_RTU_MAX_ADU_LENGTH
  |  |  ------------------
  |  |  |  |   17|     41|#define MODBUS_RTU_MAX_ADU_LENGTH 256
  |  |  ------------------
  ------------------
  |  Branch (74:9): [True: 5, False: 41]
  |  Branch (74:35): [True: 40, False: 1]
  ------------------
   75|     45|        return 0;
   76|     45|    }
   77|       |
   78|      1|    Fuzzer *fuzzer = (Fuzzer*)malloc(sizeof(Fuzzer));
   79|      1|    fuzzer->port = PORT;
  ------------------
  |  |   28|      1|#define PORT 8080
  ------------------
   80|       |
   81|      1|    fuzzer->size = size;
   82|      1|    fuzzer->buffer = data;
   83|       |
   84|      1|    pthread_create(&fuzzer->thread, NULL,client,fuzzer);
   85|      1|    server(fuzzer);
   86|      1|    pthread_join(fuzzer->thread, NULL); /* Avoid UAF*/
   87|       |
   88|      1|    free(fuzzer);
   89|      1|    return 0;
   90|     46|}
server:
   93|      1|{
   94|      1|    int s = -1;
   95|      1|    modbus_t *ctx;
   96|      1|    modbus_mapping_t *mb_mapping;
   97|      1|    int rc;
   98|      1|    int i;
   99|      1|    uint8_t *query;
  100|       |
  101|      1|    ctx = modbus_new_tcp("127.0.0.1", fuzzer->port);
  102|      1|    query = malloc(MODBUS_TCP_MAX_ADU_LENGTH);
  ------------------
  |  |   40|      1|#define MODBUS_TCP_MAX_ADU_LENGTH 260
  ------------------
  103|       |
  104|      1|    mb_mapping = modbus_mapping_new_start_address(
  105|      1|        UT_BITS_ADDRESS, UT_BITS_NB,
  106|      1|        UT_INPUT_BITS_ADDRESS, UT_INPUT_BITS_NB,
  107|      1|        UT_REGISTERS_ADDRESS, UT_REGISTERS_NB_MAX,
  108|      1|        UT_INPUT_REGISTERS_ADDRESS, UT_INPUT_REGISTERS_NB);
  109|      1|    if (mb_mapping == NULL) {
  ------------------
  |  Branch (109:9): [True: 0, False: 1]
  ------------------
  110|      0|        fprintf(stderr, "Failed to allocate the mapping: %s\n",
  111|      0|                modbus_strerror(errno));
  112|      0|        modbus_free(ctx);
  113|      0|        return -1;
  114|      0|    }
  115|       |
  116|       |    /* Initialize input values that's can be only done server side. */
  117|      1|    modbus_set_bits_from_bytes(mb_mapping->tab_input_bits, 0, UT_INPUT_BITS_NB,
  118|      1|                               UT_INPUT_BITS_TAB);
  119|       |
  120|       |    /* Initialize values of INPUT REGISTERS */
  121|      2|    for (i=0; i < UT_INPUT_REGISTERS_NB; i++) {
  ------------------
  |  Branch (121:15): [True: 1, False: 1]
  ------------------
  122|      1|        mb_mapping->tab_input_registers[i] = UT_INPUT_REGISTERS_TAB[i];
  123|      1|    }
  124|       |
  125|      1|    s = modbus_tcp_listen(ctx, 1);
  126|      1|    modbus_tcp_accept(ctx, &s);
  127|       |
  128|      1|    rc = modbus_receive(ctx, query);
  129|       |
  130|      1|    if (s != -1) {
  ------------------
  |  Branch (130:9): [True: 1, False: 0]
  ------------------
  131|      1|        close(s);
  132|      1|    }
  133|       |
  134|      1|    modbus_mapping_free(mb_mapping);
  135|      1|    free(query);
  136|       |    /* For RTU */
  137|      1|    modbus_close(ctx);
  138|      1|    modbus_free(ctx);
  139|       |
  140|      1|    return rc;
  141|      1|}

modbus_set_bits_from_bytes:
   92|      1|{
   93|      1|    unsigned int i;
   94|      1|    int shift = 0;
   95|       |
   96|     23|    for (i = idx; i < idx + nb_bits; i++) {
  ------------------
  |  Branch (96:19): [True: 22, False: 1]
  ------------------
   97|     22|        dest[i] = tab_byte[(i - idx) / 8] & (1 << shift) ? 1 : 0;
  ------------------
  |  Branch (97:19): [True: 14, False: 8]
  ------------------
   98|       |        /* gcc doesn't like: shift = (++shift) % 8; */
   99|     22|        shift++;
  100|     22|        shift %= 8;
  101|     22|    }
  102|      1|}

modbus_tcp_listen:
  506|      1|{
  507|      1|    int new_s;
  508|      1|    int enable;
  509|      1|    int flags;
  510|      1|    struct sockaddr_in addr;
  511|      1|    modbus_tcp_t *ctx_tcp;
  512|      1|    int rc;
  513|       |
  514|      1|    if (ctx == NULL) {
  ------------------
  |  Branch (514:9): [True: 0, False: 1]
  ------------------
  515|      0|        errno = EINVAL;
  516|      0|        return -1;
  517|      0|    }
  518|       |
  519|      1|    ctx_tcp = ctx->backend_data;
  520|       |
  521|       |#ifdef OS_WIN32
  522|       |    if (_modbus_tcp_init_win32() == -1) {
  523|       |        return -1;
  524|       |    }
  525|       |#endif
  526|       |
  527|      1|    flags = SOCK_STREAM;
  528|       |
  529|      1|#ifdef SOCK_CLOEXEC
  530|      1|    flags |= SOCK_CLOEXEC;
  531|      1|#endif
  532|       |
  533|      1|    new_s = socket(PF_INET, flags, IPPROTO_TCP);
  534|      1|    if (new_s == -1) {
  ------------------
  |  Branch (534:9): [True: 0, False: 1]
  ------------------
  535|      0|        return -1;
  536|      0|    }
  537|       |
  538|      1|    enable = 1;
  539|      1|    if (setsockopt(new_s, SOL_SOCKET, SO_REUSEADDR, (char *) &enable, sizeof(enable)) ==
  ------------------
  |  Branch (539:9): [True: 0, False: 1]
  ------------------
  540|      1|        -1) {
  541|      0|        close(new_s);
  542|      0|        return -1;
  543|      0|    }
  544|       |
  545|      1|    memset(&addr, 0, sizeof(addr));
  546|      1|    addr.sin_family = AF_INET;
  547|       |    /* If the modbus port is < to 1024, we need the setuid root. */
  548|      1|    addr.sin_port = htons(ctx_tcp->port);
  549|      1|    if (ctx_tcp->ip[0] == '0') {
  ------------------
  |  Branch (549:9): [True: 0, False: 1]
  ------------------
  550|       |        /* Listen any addresses */
  551|      0|        addr.sin_addr.s_addr = htonl(INADDR_ANY);
  552|      1|    } else {
  553|       |        /* Listen only specified IP address */
  554|      1|        rc = inet_pton(addr.sin_family, ctx_tcp->ip, &(addr.sin_addr));
  555|      1|        if (rc <= 0) {
  ------------------
  |  Branch (555:13): [True: 0, False: 1]
  ------------------
  556|      0|            if (ctx->debug) {
  ------------------
  |  Branch (556:17): [True: 0, False: 0]
  ------------------
  557|      0|                fprintf(stderr, "Invalid IP address: %s\n", ctx_tcp->ip);
  558|      0|            }
  559|      0|            close(new_s);
  560|      0|            return -1;
  561|      0|        }
  562|      1|    }
  563|       |
  564|      1|    if (bind(new_s, (struct sockaddr *) &addr, sizeof(addr)) == -1) {
  ------------------
  |  Branch (564:9): [True: 0, False: 1]
  ------------------
  565|      0|        close(new_s);
  566|      0|        return -1;
  567|      0|    }
  568|       |
  569|      1|    if (listen(new_s, nb_connection) == -1) {
  ------------------
  |  Branch (569:9): [True: 0, False: 1]
  ------------------
  570|      0|        close(new_s);
  571|      0|        return -1;
  572|      0|    }
  573|       |
  574|      1|    return new_s;
  575|      1|}
modbus_tcp_accept:
  694|      1|{
  695|      1|    struct sockaddr_in addr;
  696|      1|    socklen_t addrlen;
  697|       |
  698|      1|    if (ctx == NULL) {
  ------------------
  |  Branch (698:9): [True: 0, False: 1]
  ------------------
  699|      0|        errno = EINVAL;
  700|      0|        return -1;
  701|      0|    }
  702|       |
  703|      1|    addrlen = sizeof(addr);
  704|      1|#ifdef HAVE_ACCEPT4
  705|       |    /* Inherit socket flags and use accept4 call */
  706|      1|    ctx->s = accept4(*s, (struct sockaddr *) &addr, &addrlen, SOCK_CLOEXEC);
  707|       |#else
  708|       |    ctx->s = accept(*s, (struct sockaddr *) &addr, &addrlen);
  709|       |#endif
  710|       |
  711|      1|    if (ctx->s < 0) {
  ------------------
  |  Branch (711:9): [True: 0, False: 1]
  ------------------
  712|      0|        return -1;
  713|      0|    }
  714|       |
  715|      1|    if (ctx->debug) {
  ------------------
  |  Branch (715:9): [True: 0, False: 1]
  ------------------
  716|      0|        char buf[INET_ADDRSTRLEN];
  717|      0|        if (inet_ntop(AF_INET, &(addr.sin_addr), buf, INET_ADDRSTRLEN) == NULL) {
  ------------------
  |  Branch (717:13): [True: 0, False: 0]
  ------------------
  718|      0|            fprintf(stderr, "Client connection accepted from unparsable IP.\n");
  719|      0|        } else {
  720|      0|            printf("Client connection accepted from %s.\n", buf);
  721|      0|        }
  722|      0|    }
  723|       |
  724|      1|    return ctx->s;
  725|      1|}
modbus_new_tcp:
  856|      1|{
  857|      1|    modbus_t *ctx;
  858|      1|    modbus_tcp_t *ctx_tcp;
  859|      1|    size_t dest_size;
  860|      1|    size_t ret_size;
  861|       |
  862|       |#if defined(OS_BSD)
  863|       |    /* MSG_NOSIGNAL is unsupported on *BSD so we install an ignore
  864|       |       handler for SIGPIPE. */
  865|       |    struct sigaction sa;
  866|       |
  867|       |    sa.sa_handler = SIG_IGN;
  868|       |    if (sigaction(SIGPIPE, &sa, NULL) < 0) {
  869|       |        /* The debug flag can't be set here... */
  870|       |        fprintf(stderr, "Could not install SIGPIPE handler.\n");
  871|       |        return NULL;
  872|       |    }
  873|       |#endif
  874|       |
  875|      1|    ctx = (modbus_t *) malloc(sizeof(modbus_t));
  876|      1|    if (ctx == NULL) {
  ------------------
  |  Branch (876:9): [True: 0, False: 1]
  ------------------
  877|      0|        return NULL;
  878|      0|    }
  879|      1|    _modbus_init_common(ctx);
  880|       |
  881|       |    /* Could be changed after to reach a remote serial Modbus device */
  882|      1|    ctx->slave = MODBUS_TCP_SLAVE;
  ------------------
  |  |   35|      1|#define MODBUS_TCP_SLAVE        0xFF
  ------------------
  883|       |
  884|      1|    ctx->backend = &_modbus_tcp_backend;
  885|       |
  886|      1|    ctx->backend_data = (modbus_tcp_t *) malloc(sizeof(modbus_tcp_t));
  887|      1|    if (ctx->backend_data == NULL) {
  ------------------
  |  Branch (887:9): [True: 0, False: 1]
  ------------------
  888|      0|        modbus_free(ctx);
  889|      0|        errno = ENOMEM;
  890|      0|        return NULL;
  891|      0|    }
  892|      1|    ctx_tcp = (modbus_tcp_t *) ctx->backend_data;
  893|       |
  894|      1|    if (ip != NULL) {
  ------------------
  |  Branch (894:9): [True: 1, False: 0]
  ------------------
  895|      1|        dest_size = sizeof(char) * 16;
  896|      1|        ret_size = strlcpy(ctx_tcp->ip, ip, dest_size);
  897|      1|        if (ret_size == 0) {
  ------------------
  |  Branch (897:13): [True: 0, False: 1]
  ------------------
  898|      0|            fprintf(stderr, "The IP string is empty\n");
  899|      0|            modbus_free(ctx);
  900|      0|            errno = EINVAL;
  901|      0|            return NULL;
  902|      0|        }
  903|       |
  904|      1|        if (ret_size >= dest_size) {
  ------------------
  |  Branch (904:13): [True: 0, False: 1]
  ------------------
  905|      0|            fprintf(stderr, "The IP string has been truncated\n");
  906|      0|            modbus_free(ctx);
  907|      0|            errno = EINVAL;
  908|      0|            return NULL;
  909|      0|        }
  910|      1|    } else {
  911|      0|        ctx_tcp->ip[0] = '0';
  912|      0|    }
  913|      1|    ctx_tcp->port = port;
  914|      1|    ctx_tcp->t_id = 0;
  915|       |
  916|      1|    return ctx;
  917|      1|}
modbus-tcp.c:_modbus_tcp_receive:
  180|      1|{
  181|      1|    return _modbus_receive_msg(ctx, req, MSG_INDICATION);
  182|      1|}
modbus-tcp.c:_modbus_tcp_recv:
  185|      1|{
  186|      1|    return recv(ctx->s, (char *) rsp, rsp_length, 0);
  187|      1|}
modbus-tcp.c:_modbus_tcp_check_integrity:
  190|      1|{
  191|      1|    return msg_length;
  192|      1|}
modbus-tcp.c:_modbus_tcp_is_connected:
  453|      1|{
  454|      1|    return ctx->s >= 0;
  455|      1|}
modbus-tcp.c:_modbus_tcp_close:
  459|      1|{
  460|      1|    if (ctx->s >= 0) {
  ------------------
  |  Branch (460:9): [True: 1, False: 0]
  ------------------
  461|      1|        shutdown(ctx->s, SHUT_RDWR);
  462|      1|        close(ctx->s);
  463|      1|        ctx->s = -1;
  464|      1|    }
  465|      1|}
modbus-tcp.c:_modbus_tcp_select:
  763|      1|{
  764|      1|    int s_rc;
  765|      1|    while ((s_rc = select(ctx->s + 1, rset, NULL, NULL, tv)) == -1) {
  ------------------
  |  Branch (765:12): [True: 0, False: 1]
  ------------------
  766|      0|        if (errno == EINTR) {
  ------------------
  |  Branch (766:13): [True: 0, False: 0]
  ------------------
  767|      0|            if (ctx->debug) {
  ------------------
  |  Branch (767:17): [True: 0, False: 0]
  ------------------
  768|      0|                fprintf(stderr, "A non blocked signal was caught\n");
  769|      0|            }
  770|       |            /* Necessary after an error */
  771|      0|            FD_ZERO(rset);
  772|      0|            FD_SET(ctx->s, rset);
  773|      0|        } else {
  774|      0|            return -1;
  775|      0|        }
  776|      0|    }
  777|       |
  778|      1|    if (s_rc == 0) {
  ------------------
  |  Branch (778:9): [True: 0, False: 1]
  ------------------
  779|      0|        errno = ETIMEDOUT;
  780|      0|        return -1;
  781|      0|    }
  782|       |
  783|      1|    return s_rc;
  784|      1|}
modbus-tcp.c:_modbus_tcp_free:
  787|      1|{
  788|      1|    if (ctx->backend_data) {
  ------------------
  |  Branch (788:9): [True: 1, False: 0]
  ------------------
  789|      1|        free(ctx->backend_data);
  790|      1|    }
  791|      1|    free(ctx);
  792|      1|}

_modbus_receive_msg:
  351|      1|{
  352|      1|    int rc;
  353|      1|    fd_set rset;
  354|      1|    struct timeval tv;
  355|      1|    struct timeval *p_tv;
  356|      1|    unsigned int length_to_read;
  357|      1|    int msg_length = 0;
  358|      1|    _step_t step;
  359|       |#ifdef _WIN32
  360|       |    int wsa_err;
  361|       |#endif
  362|       |
  363|      1|    if (ctx->debug) {
  ------------------
  |  Branch (363:9): [True: 0, False: 1]
  ------------------
  364|      0|        if (msg_type == MSG_INDICATION) {
  ------------------
  |  Branch (364:13): [True: 0, False: 0]
  ------------------
  365|      0|            printf("Waiting for an indication...\n");
  366|      0|        } else {
  367|      0|            printf("Waiting for a confirmation...\n");
  368|      0|        }
  369|      0|    }
  370|       |
  371|      1|    if (!ctx->backend->is_connected(ctx)) {
  ------------------
  |  Branch (371:9): [True: 0, False: 1]
  ------------------
  372|      0|        if (ctx->debug) {
  ------------------
  |  Branch (372:13): [True: 0, False: 0]
  ------------------
  373|      0|            fprintf(stderr, "ERROR The connection is not established.\n");
  374|      0|        }
  375|      0|        return -1;
  376|      0|    }
  377|       |
  378|       |    /* Add a file descriptor to the set */
  379|      1|    FD_ZERO(&rset);
  380|      1|    FD_SET(ctx->s, &rset);
  381|       |
  382|       |    /* We need to analyse the message step by step.  At the first step, we want
  383|       |     * to reach the function code because all packets contain this
  384|       |     * information. */
  385|      1|    step = _STEP_FUNCTION;
  386|      1|    length_to_read = ctx->backend->header_length + 1;
  387|       |
  388|      1|    if (msg_type == MSG_INDICATION) {
  ------------------
  |  Branch (388:9): [True: 1, False: 0]
  ------------------
  389|       |        /* Wait for a message, we don't know when the message will be
  390|       |         * received */
  391|      1|        if (ctx->indication_timeout.tv_sec == 0 && ctx->indication_timeout.tv_usec == 0) {
  ------------------
  |  Branch (391:13): [True: 1, False: 0]
  |  Branch (391:52): [True: 1, False: 0]
  ------------------
  392|       |            /* By default, the indication timeout isn't set */
  393|      1|            p_tv = NULL;
  394|      1|        } else {
  395|       |            /* Wait for an indication (name of a received request by a server, see schema)
  396|       |             */
  397|      0|            tv.tv_sec = ctx->indication_timeout.tv_sec;
  398|      0|            tv.tv_usec = ctx->indication_timeout.tv_usec;
  399|      0|            p_tv = &tv;
  400|      0|        }
  401|      1|    } else {
  402|      0|        tv.tv_sec = ctx->response_timeout.tv_sec;
  403|      0|        tv.tv_usec = ctx->response_timeout.tv_usec;
  404|      0|        p_tv = &tv;
  405|      0|    }
  406|       |
  407|      2|    while (length_to_read != 0) {
  ------------------
  |  Branch (407:12): [True: 1, False: 1]
  ------------------
  408|      1|        rc = ctx->backend->select(ctx, &rset, p_tv, length_to_read);
  409|      1|        if (rc == -1) {
  ------------------
  |  Branch (409:13): [True: 0, False: 1]
  ------------------
  410|      0|            _error_print(ctx, "select");
  411|      0|            if (ctx->error_recovery & MODBUS_ERROR_RECOVERY_LINK) {
  ------------------
  |  Branch (411:17): [True: 0, False: 0]
  ------------------
  412|       |#ifdef _WIN32
  413|       |                wsa_err = WSAGetLastError();
  414|       |
  415|       |                // no equivalent to ETIMEDOUT when select fails on Windows
  416|       |                if (wsa_err == WSAENETDOWN || wsa_err == WSAENOTSOCK) {
  417|       |                    modbus_close(ctx);
  418|       |                    modbus_connect(ctx);
  419|       |                }
  420|       |#else
  421|      0|                int saved_errno = errno;
  422|       |
  423|      0|                if (errno == ETIMEDOUT) {
  ------------------
  |  Branch (423:21): [True: 0, False: 0]
  ------------------
  424|      0|                    _sleep_response_timeout(ctx);
  425|      0|                    modbus_flush(ctx);
  426|      0|                } else if (errno == EBADF) {
  ------------------
  |  Branch (426:28): [True: 0, False: 0]
  ------------------
  427|      0|                    modbus_close(ctx);
  428|      0|                    modbus_connect(ctx);
  429|      0|                }
  430|      0|                errno = saved_errno;
  431|      0|#endif
  432|      0|            }
  433|      0|            return -1;
  434|      0|        }
  435|       |
  436|      1|        rc = ctx->backend->recv(ctx, msg + msg_length, length_to_read);
  437|      1|        if (rc == 0) {
  ------------------
  |  Branch (437:13): [True: 0, False: 1]
  ------------------
  438|      0|            errno = ECONNRESET;
  439|      0|            rc = -1;
  440|      0|        }
  441|       |
  442|      1|        if (rc == -1) {
  ------------------
  |  Branch (442:13): [True: 0, False: 1]
  ------------------
  443|      0|            _error_print(ctx, "read");
  444|       |#ifdef _WIN32
  445|       |            wsa_err = WSAGetLastError();
  446|       |            if ((ctx->error_recovery & MODBUS_ERROR_RECOVERY_LINK) &&
  447|       |                (ctx->backend->backend_type == _MODBUS_BACKEND_TYPE_TCP) &&
  448|       |                (wsa_err == WSAENOTCONN || wsa_err == WSAENETRESET ||
  449|       |                 wsa_err == WSAENOTSOCK || wsa_err == WSAESHUTDOWN ||
  450|       |                 wsa_err == WSAECONNABORTED || wsa_err == WSAETIMEDOUT ||
  451|       |                 wsa_err == WSAECONNRESET)) {
  452|       |                modbus_close(ctx);
  453|       |                modbus_connect(ctx);
  454|       |            }
  455|       |#else
  456|      0|            if ((ctx->error_recovery & MODBUS_ERROR_RECOVERY_LINK) &&
  ------------------
  |  Branch (456:17): [True: 0, False: 0]
  ------------------
  457|      0|                (ctx->backend->backend_type == _MODBUS_BACKEND_TYPE_TCP) &&
  ------------------
  |  Branch (457:17): [True: 0, False: 0]
  ------------------
  458|      0|                (errno == ECONNRESET || errno == ECONNREFUSED || errno == EBADF)) {
  ------------------
  |  Branch (458:18): [True: 0, False: 0]
  |  Branch (458:41): [True: 0, False: 0]
  |  Branch (458:66): [True: 0, False: 0]
  ------------------
  459|      0|                int saved_errno = errno;
  460|      0|                modbus_close(ctx);
  461|      0|                modbus_connect(ctx);
  462|       |                /* Could be removed by previous calls */
  463|      0|                errno = saved_errno;
  464|      0|            }
  465|      0|#endif
  466|      0|            return -1;
  467|      0|        }
  468|       |
  469|       |        /* Display the hex code of each character received */
  470|      1|        if (ctx->debug) {
  ------------------
  |  Branch (470:13): [True: 0, False: 1]
  ------------------
  471|      0|            int i;
  472|      0|            for (i = 0; i < rc; i++)
  ------------------
  |  Branch (472:25): [True: 0, False: 0]
  ------------------
  473|      0|                printf("<%.2X>", msg[msg_length + i]);
  474|      0|        }
  475|       |
  476|       |        /* Sums bytes received */
  477|      1|        msg_length += rc;
  478|       |        /* Computes remaining bytes */
  479|      1|        length_to_read -= rc;
  480|       |
  481|      1|        if (length_to_read == 0) {
  ------------------
  |  Branch (481:13): [True: 1, False: 0]
  ------------------
  482|      1|            switch (step) {
  483|      1|            case _STEP_FUNCTION:
  ------------------
  |  Branch (483:13): [True: 1, False: 0]
  ------------------
  484|       |                /* Function code position */
  485|      1|                length_to_read = compute_meta_length_after_function(
  486|      1|                    msg[ctx->backend->header_length], msg_type);
  487|      1|                if (length_to_read != 0) {
  ------------------
  |  Branch (487:21): [True: 0, False: 1]
  ------------------
  488|      0|                    step = _STEP_META;
  489|      0|                    break;
  490|      0|                } /* else switches straight to the next step */
  491|      1|            case _STEP_META:
  ------------------
  |  Branch (491:13): [True: 0, False: 1]
  ------------------
  492|      1|                length_to_read = compute_data_length_after_meta(ctx, msg, msg_type);
  493|      1|                if ((msg_length + length_to_read) > ctx->backend->max_adu_length) {
  ------------------
  |  Branch (493:21): [True: 0, False: 1]
  ------------------
  494|      0|                    errno = EMBBADDATA;
  ------------------
  |  |  147|      0|#define EMBBADDATA  (EMBXGTAR + 2)
  |  |  ------------------
  |  |  |  |  143|      0|#define EMBXGTAR   (MODBUS_ENOBASE + MODBUS_EXCEPTION_GATEWAY_TARGET)
  |  |  |  |  ------------------
  |  |  |  |  |  |  116|      0|#define MODBUS_ENOBASE 112345678
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
  495|      0|                    _error_print(ctx, "too many data");
  496|      0|                    return -1;
  497|      0|                }
  498|      1|                step = _STEP_DATA;
  499|      1|                break;
  500|      0|            default:
  ------------------
  |  Branch (500:13): [True: 0, False: 1]
  ------------------
  501|      0|                break;
  502|      1|            }
  503|      1|        }
  504|       |
  505|      1|        if (length_to_read > 0 &&
  ------------------
  |  Branch (505:13): [True: 0, False: 1]
  ------------------
  506|      1|            (ctx->byte_timeout.tv_sec > 0 || ctx->byte_timeout.tv_usec > 0)) {
  ------------------
  |  Branch (506:14): [True: 0, False: 0]
  |  Branch (506:46): [True: 0, False: 0]
  ------------------
  507|       |            /* If there is no character in the buffer, the allowed timeout
  508|       |               interval between two consecutive bytes is defined by
  509|       |               byte_timeout */
  510|      0|            tv.tv_sec = ctx->byte_timeout.tv_sec;
  511|      0|            tv.tv_usec = ctx->byte_timeout.tv_usec;
  512|      0|            p_tv = &tv;
  513|      0|        }
  514|       |        /* else timeout isn't set again, the full response must be read before
  515|       |           expiration of response timeout (for CONFIRMATION only) */
  516|      1|    }
  517|       |
  518|      1|    if (ctx->debug)
  ------------------
  |  Branch (518:9): [True: 0, False: 1]
  ------------------
  519|      0|        printf("\n");
  520|       |
  521|      1|    return ctx->backend->check_integrity(ctx, msg, msg_length);
  522|      1|}
modbus_receive:
  526|      1|{
  527|      1|    if (ctx == NULL) {
  ------------------
  |  Branch (527:9): [True: 0, False: 1]
  ------------------
  528|      0|        errno = EINVAL;
  529|      0|        return -1;
  530|      0|    }
  531|       |
  532|      1|    return ctx->backend->receive(ctx, req);
  533|      1|}
_modbus_init_common:
 1699|      1|{
 1700|       |    /* Slave and socket are initialized to -1 */
 1701|      1|    ctx->slave = -1;
 1702|      1|    ctx->s = -1;
 1703|       |
 1704|      1|    ctx->debug = FALSE;
  ------------------
  |  |   47|      1|#define FALSE 0
  ------------------
 1705|      1|    ctx->error_recovery = MODBUS_ERROR_RECOVERY_NONE;
 1706|      1|    ctx->quirks = MODBUS_QUIRK_NONE;
 1707|       |
 1708|      1|    ctx->response_timeout.tv_sec = 0;
 1709|      1|    ctx->response_timeout.tv_usec = _RESPONSE_TIMEOUT;
  ------------------
  |  |   41|      1|#define _RESPONSE_TIMEOUT 500000
  ------------------
 1710|       |
 1711|      1|    ctx->byte_timeout.tv_sec = 0;
 1712|      1|    ctx->byte_timeout.tv_usec = _BYTE_TIMEOUT;
  ------------------
  |  |   42|      1|#define _BYTE_TIMEOUT     500000
  ------------------
 1713|       |
 1714|      1|    ctx->indication_timeout.tv_sec = 0;
 1715|      1|    ctx->indication_timeout.tv_usec = 0;
 1716|      1|}
modbus_close:
 1895|      1|{
 1896|      1|    if (ctx == NULL)
  ------------------
  |  Branch (1896:9): [True: 0, False: 1]
  ------------------
 1897|      0|        return;
 1898|       |
 1899|      1|    ctx->backend->close(ctx);
 1900|      1|}
modbus_free:
 1903|      1|{
 1904|      1|    if (ctx == NULL)
  ------------------
  |  Branch (1904:9): [True: 0, False: 1]
  ------------------
 1905|      0|        return;
 1906|       |
 1907|      1|    ctx->backend->free(ctx);
 1908|      1|}
modbus_mapping_new_start_address:
 1935|      1|{
 1936|      1|    modbus_mapping_t *mb_mapping;
 1937|       |
 1938|      1|    mb_mapping = (modbus_mapping_t *) malloc(sizeof(modbus_mapping_t));
 1939|      1|    if (mb_mapping == NULL) {
  ------------------
  |  Branch (1939:9): [True: 0, False: 1]
  ------------------
 1940|      0|        return NULL;
 1941|      0|    }
 1942|       |
 1943|       |    /* 0X */
 1944|      1|    mb_mapping->nb_bits = nb_bits;
 1945|      1|    mb_mapping->start_bits = start_bits;
 1946|      1|    if (nb_bits == 0) {
  ------------------
  |  Branch (1946:9): [True: 0, False: 1]
  ------------------
 1947|      0|        mb_mapping->tab_bits = NULL;
 1948|      1|    } else {
 1949|       |        /* Negative number raises a POSIX error */
 1950|      1|        mb_mapping->tab_bits = (uint8_t *) malloc(nb_bits * sizeof(uint8_t));
 1951|      1|        if (mb_mapping->tab_bits == NULL) {
  ------------------
  |  Branch (1951:13): [True: 0, False: 1]
  ------------------
 1952|      0|            free(mb_mapping);
 1953|      0|            return NULL;
 1954|      0|        }
 1955|      1|        memset(mb_mapping->tab_bits, 0, nb_bits * sizeof(uint8_t));
 1956|      1|    }
 1957|       |
 1958|       |    /* 1X */
 1959|      1|    mb_mapping->nb_input_bits = nb_input_bits;
 1960|      1|    mb_mapping->start_input_bits = start_input_bits;
 1961|      1|    if (nb_input_bits == 0) {
  ------------------
  |  Branch (1961:9): [True: 0, False: 1]
  ------------------
 1962|      0|        mb_mapping->tab_input_bits = NULL;
 1963|      1|    } else {
 1964|      1|        mb_mapping->tab_input_bits = (uint8_t *) malloc(nb_input_bits * sizeof(uint8_t));
 1965|      1|        if (mb_mapping->tab_input_bits == NULL) {
  ------------------
  |  Branch (1965:13): [True: 0, False: 1]
  ------------------
 1966|      0|            free(mb_mapping->tab_bits);
 1967|      0|            free(mb_mapping);
 1968|      0|            return NULL;
 1969|      0|        }
 1970|      1|        memset(mb_mapping->tab_input_bits, 0, nb_input_bits * sizeof(uint8_t));
 1971|      1|    }
 1972|       |
 1973|       |    /* 4X */
 1974|      1|    mb_mapping->nb_registers = nb_registers;
 1975|      1|    mb_mapping->start_registers = start_registers;
 1976|      1|    if (nb_registers == 0) {
  ------------------
  |  Branch (1976:9): [True: 0, False: 1]
  ------------------
 1977|      0|        mb_mapping->tab_registers = NULL;
 1978|      1|    } else {
 1979|      1|        mb_mapping->tab_registers = (uint16_t *) malloc(nb_registers * sizeof(uint16_t));
 1980|      1|        if (mb_mapping->tab_registers == NULL) {
  ------------------
  |  Branch (1980:13): [True: 0, False: 1]
  ------------------
 1981|      0|            free(mb_mapping->tab_input_bits);
 1982|      0|            free(mb_mapping->tab_bits);
 1983|      0|            free(mb_mapping);
 1984|      0|            return NULL;
 1985|      0|        }
 1986|      1|        memset(mb_mapping->tab_registers, 0, nb_registers * sizeof(uint16_t));
 1987|      1|    }
 1988|       |
 1989|       |    /* 3X */
 1990|      1|    mb_mapping->nb_input_registers = nb_input_registers;
 1991|      1|    mb_mapping->start_input_registers = start_input_registers;
 1992|      1|    if (nb_input_registers == 0) {
  ------------------
  |  Branch (1992:9): [True: 0, False: 1]
  ------------------
 1993|      0|        mb_mapping->tab_input_registers = NULL;
 1994|      1|    } else {
 1995|      1|        mb_mapping->tab_input_registers =
 1996|      1|            (uint16_t *) malloc(nb_input_registers * sizeof(uint16_t));
 1997|      1|        if (mb_mapping->tab_input_registers == NULL) {
  ------------------
  |  Branch (1997:13): [True: 0, False: 1]
  ------------------
 1998|      0|            free(mb_mapping->tab_registers);
 1999|      0|            free(mb_mapping->tab_input_bits);
 2000|      0|            free(mb_mapping->tab_bits);
 2001|      0|            free(mb_mapping);
 2002|      0|            return NULL;
 2003|      0|        }
 2004|      1|        memset(mb_mapping->tab_input_registers, 0, nb_input_registers * sizeof(uint16_t));
 2005|      1|    }
 2006|       |
 2007|      1|    return mb_mapping;
 2008|      1|}
modbus_mapping_free:
 2021|      1|{
 2022|      1|    if (mb_mapping == NULL) {
  ------------------
  |  Branch (2022:9): [True: 0, False: 1]
  ------------------
 2023|      0|        return;
 2024|      0|    }
 2025|       |
 2026|      1|    free(mb_mapping->tab_input_registers);
 2027|      1|    free(mb_mapping->tab_registers);
 2028|      1|    free(mb_mapping->tab_input_bits);
 2029|      1|    free(mb_mapping->tab_bits);
 2030|      1|    free(mb_mapping);
 2031|      1|}
strlcpy:
 2047|      1|{
 2048|      1|    register char *d = dest;
 2049|      1|    register const char *s = src;
 2050|      1|    register size_t n = dest_size;
 2051|       |
 2052|       |    /* Copy as many bytes as will fit */
 2053|      1|    if (n != 0 && --n != 0) {
  ------------------
  |  Branch (2053:9): [True: 1, False: 0]
  |  Branch (2053:19): [True: 1, False: 0]
  ------------------
 2054|     10|        do {
 2055|     10|            if ((*d++ = *s++) == 0)
  ------------------
  |  Branch (2055:17): [True: 1, False: 9]
  ------------------
 2056|      1|                break;
 2057|     10|        } while (--n != 0);
  ------------------
  |  Branch (2057:18): [True: 9, False: 0]
  ------------------
 2058|      1|    }
 2059|       |
 2060|       |    /* Not enough room in dest, add NUL and traverse rest of src */
 2061|      1|    if (n == 0) {
  ------------------
  |  Branch (2061:9): [True: 0, False: 1]
  ------------------
 2062|      0|        if (dest_size != 0)
  ------------------
  |  Branch (2062:13): [True: 0, False: 0]
  ------------------
 2063|      0|            *d = '\0'; /* NUL-terminate dest */
 2064|      0|        while (*s++)
  ------------------
  |  Branch (2064:16): [True: 0, False: 0]
  ------------------
 2065|      0|            ;
 2066|      0|    }
 2067|       |
 2068|      1|    return (s - src - 1); /* count does not include NUL */
 2069|      1|}
modbus.c:compute_meta_length_after_function:
  266|      1|{
  267|      1|    int length;
  268|       |
  269|      1|    if (msg_type == MSG_INDICATION) {
  ------------------
  |  Branch (269:9): [True: 1, False: 0]
  ------------------
  270|      1|        if (function <= MODBUS_FC_WRITE_SINGLE_REGISTER) {
  ------------------
  |  |   68|      1|#define MODBUS_FC_WRITE_SINGLE_REGISTER    0x06
  ------------------
  |  Branch (270:13): [True: 0, False: 1]
  ------------------
  271|      0|            length = 4;
  272|      1|        } else if (function == MODBUS_FC_WRITE_MULTIPLE_COILS ||
  ------------------
  |  |   70|      2|#define MODBUS_FC_WRITE_MULTIPLE_COILS     0x0F
  ------------------
  |  Branch (272:20): [True: 0, False: 1]
  ------------------
  273|      1|                   function == MODBUS_FC_WRITE_MULTIPLE_REGISTERS) {
  ------------------
  |  |   71|      1|#define MODBUS_FC_WRITE_MULTIPLE_REGISTERS 0x10
  ------------------
  |  Branch (273:20): [True: 0, False: 1]
  ------------------
  274|      0|            length = 5;
  275|      1|        } else if (function == MODBUS_FC_MASK_WRITE_REGISTER) {
  ------------------
  |  |   73|      1|#define MODBUS_FC_MASK_WRITE_REGISTER      0x16
  ------------------
  |  Branch (275:20): [True: 0, False: 1]
  ------------------
  276|      0|            length = 6;
  277|      1|        } else if (function == MODBUS_FC_WRITE_AND_READ_REGISTERS) {
  ------------------
  |  |   74|      1|#define MODBUS_FC_WRITE_AND_READ_REGISTERS 0x17
  ------------------
  |  Branch (277:20): [True: 0, False: 1]
  ------------------
  278|      0|            length = 9;
  279|      1|        } else {
  280|       |            /* MODBUS_FC_READ_EXCEPTION_STATUS, MODBUS_FC_REPORT_SLAVE_ID */
  281|      1|            length = 0;
  282|      1|        }
  283|      1|    } else {
  284|       |        /* MSG_CONFIRMATION */
  285|      0|        switch (function) {
  286|      0|        case MODBUS_FC_WRITE_SINGLE_COIL:
  ------------------
  |  |   67|      0|#define MODBUS_FC_WRITE_SINGLE_COIL        0x05
  ------------------
  |  Branch (286:9): [True: 0, False: 0]
  ------------------
  287|      0|        case MODBUS_FC_WRITE_SINGLE_REGISTER:
  ------------------
  |  |   68|      0|#define MODBUS_FC_WRITE_SINGLE_REGISTER    0x06
  ------------------
  |  Branch (287:9): [True: 0, False: 0]
  ------------------
  288|      0|        case MODBUS_FC_WRITE_MULTIPLE_COILS:
  ------------------
  |  |   70|      0|#define MODBUS_FC_WRITE_MULTIPLE_COILS     0x0F
  ------------------
  |  Branch (288:9): [True: 0, False: 0]
  ------------------
  289|      0|        case MODBUS_FC_WRITE_MULTIPLE_REGISTERS:
  ------------------
  |  |   71|      0|#define MODBUS_FC_WRITE_MULTIPLE_REGISTERS 0x10
  ------------------
  |  Branch (289:9): [True: 0, False: 0]
  ------------------
  290|      0|            length = 4;
  291|      0|            break;
  292|      0|        case MODBUS_FC_MASK_WRITE_REGISTER:
  ------------------
  |  |   73|      0|#define MODBUS_FC_MASK_WRITE_REGISTER      0x16
  ------------------
  |  Branch (292:9): [True: 0, False: 0]
  ------------------
  293|      0|            length = 6;
  294|      0|            break;
  295|      0|        default:
  ------------------
  |  Branch (295:9): [True: 0, False: 0]
  ------------------
  296|      0|            length = 1;
  297|      0|        }
  298|      0|    }
  299|       |
  300|      1|    return length;
  301|      1|}
modbus.c:compute_data_length_after_meta:
  306|      1|{
  307|      1|    int function = msg[ctx->backend->header_length];
  308|      1|    int length;
  309|       |
  310|      1|    if (msg_type == MSG_INDICATION) {
  ------------------
  |  Branch (310:9): [True: 1, False: 0]
  ------------------
  311|      1|        switch (function) {
  312|      0|        case MODBUS_FC_WRITE_MULTIPLE_COILS:
  ------------------
  |  |   70|      0|#define MODBUS_FC_WRITE_MULTIPLE_COILS     0x0F
  ------------------
  |  Branch (312:9): [True: 0, False: 1]
  ------------------
  313|      0|        case MODBUS_FC_WRITE_MULTIPLE_REGISTERS:
  ------------------
  |  |   71|      0|#define MODBUS_FC_WRITE_MULTIPLE_REGISTERS 0x10
  ------------------
  |  Branch (313:9): [True: 0, False: 1]
  ------------------
  314|      0|            length = msg[ctx->backend->header_length + 5];
  315|      0|            break;
  316|      0|        case MODBUS_FC_WRITE_AND_READ_REGISTERS:
  ------------------
  |  |   74|      0|#define MODBUS_FC_WRITE_AND_READ_REGISTERS 0x17
  ------------------
  |  Branch (316:9): [True: 0, False: 1]
  ------------------
  317|      0|            length = msg[ctx->backend->header_length + 9];
  318|      0|            break;
  319|      1|        default:
  ------------------
  |  Branch (319:9): [True: 1, False: 0]
  ------------------
  320|      1|            length = 0;
  321|      1|        }
  322|      1|    } else {
  323|       |        /* MSG_CONFIRMATION */
  324|      0|        if (function <= MODBUS_FC_READ_INPUT_REGISTERS ||
  ------------------
  |  |   66|      0|#define MODBUS_FC_READ_INPUT_REGISTERS     0x04
  ------------------
  |  Branch (324:13): [True: 0, False: 0]
  ------------------
  325|      0|            function == MODBUS_FC_REPORT_SLAVE_ID ||
  ------------------
  |  |   72|      0|#define MODBUS_FC_REPORT_SLAVE_ID          0x11
  ------------------
  |  Branch (325:13): [True: 0, False: 0]
  ------------------
  326|      0|            function == MODBUS_FC_WRITE_AND_READ_REGISTERS) {
  ------------------
  |  |   74|      0|#define MODBUS_FC_WRITE_AND_READ_REGISTERS 0x17
  ------------------
  |  Branch (326:13): [True: 0, False: 0]
  ------------------
  327|      0|            length = msg[ctx->backend->header_length + 1];
  328|      0|        } else {
  329|      0|            length = 0;
  330|      0|        }
  331|      0|    }
  332|       |
  333|      1|    length += ctx->backend->checksum_length;
  334|       |
  335|      1|    return length;
  336|      1|}

