Coverage Report

Created: 2024-01-26 01:52

/work/testing/misc_tools.c
Line
Count
Source (jump to first uncovered line)
1
/* SPDX-License-Identifier: GPL-3.0-or-later
2
 * Copyright © 2016-2018 The TokTok team.
3
 * Copyright © 2013 Tox project.
4
 */
5
6
/*
7
 * Miscellaneous functions and data structures for doing random things.
8
 */
9
#ifndef _POSIX_C_SOURCE
10
// For nanosleep().
11
#define _POSIX_C_SOURCE 200112L
12
#endif
13
14
#include "misc_tools.h"
15
16
#include <assert.h>
17
#include <ctype.h>
18
#include <stdint.h>
19
#include <stdio.h>
20
#include <stdlib.h>
21
#include <string.h>
22
23
#include <sodium.h>
24
25
#if defined(_WIN32) || defined(__WIN32__) || defined(WIN32)
26
#include <windows.h>
27
#else
28
#include <time.h>
29
#endif
30
31
#include "../toxcore/ccompat.h"
32
#include "../toxcore/tox.h"
33
34
void c_sleep(uint32_t x)
35
47.3k
{
36
#if defined(_WIN32) || defined(__WIN32__) || defined(WIN32)
37
    Sleep(x);
38
#else
39
47.3k
    struct timespec req;
40
47.3k
    req.tv_sec = x / 1000;
41
47.3k
    req.tv_nsec = (long)x % 1000 * 1000 * 1000;
42
47.3k
    nanosleep(&req, nullptr);
43
47.3k
#endif
44
47.3k
}
45
46
// You are responsible for freeing the return value!
47
uint8_t *hex_string_to_bin(const char *hex_string)
48
0
{
49
    // byte is represented by exactly 2 hex digits, so length of binary string
50
    // is half of that of the hex one. only hex string with even length
51
    // valid. the more proper implementation would be to check if strlen(hex_string)
52
    // is odd and return error code if it is. we assume strlen is even. if it's not
53
    // then the last byte just won't be written in 'ret'.
54
0
    size_t i, len = strlen(hex_string) / 2;
55
0
    uint8_t *ret = (uint8_t *)malloc(len);
56
0
    const char *pos = hex_string;
57
58
0
    if (ret == nullptr) {
59
0
        return nullptr;
60
0
    }
61
62
0
    for (i = 0; i < len; ++i, pos += 2) {
63
0
        unsigned int val;
64
0
        sscanf(pos, "%02x", &val);
65
0
        ret[i] = val;
66
0
    }
67
68
0
    return ret;
69
0
}
70
71
void to_hex(char *out, uint8_t *in, int size)
72
1
{
73
39
    while (size--) {
74
38
        if (*in >> 4 < 0xA) {
75
25
            *out++ = '0' + (*in >> 4);
76
25
        } else {
77
13
            *out++ = 'A' + (*in >> 4) - 0xA;
78
13
        }
79
80
38
        if ((*in & 0xf) < 0xA) {
81
17
            *out++ = '0' + (*in & 0xF);
82
21
        } else {
83
21
            *out++ = 'A' + (*in & 0xF) - 0xA;
84
21
        }
85
86
38
        in++;
87
38
    }
88
1
}
89
90
/* Reimplementation of strncasecmp() function from strings.h, as strings.h is
91
 * POSIX and not portable. Specifically it doesn't exist on MSVC.
92
 */
93
int tox_strncasecmp(const char *s1, const char *s2, size_t n)
94
288
{
95
1.27k
    while (n--) {
96
1.11k
        int c1 = tolower(*(s1++));
97
1.11k
        int c2 = tolower(*(s2++));
98
99
1.11k
        if (c1 == '\0' || c2 == '\0' || c1 != c2) {
100
126
            return c1 - c2;
101
126
        }
102
1.11k
    }
103
104
162
    return 0;
105
288
}
106
107
int cmdline_parsefor_ipv46(int argc, char **argv, bool *ipv6enabled)
108
0
{
109
0
    int argvoffset = 0, argi;
110
111
0
    for (argi = 1; argi < argc; argi++) {
112
0
        if (!tox_strncasecmp(argv[argi], "--ipv", 5)) {
113
0
            if (argv[argi][5] && !argv[argi][6]) {
114
0
                char c = argv[argi][5];
115
116
0
                if (c == '4') {
117
0
                    *ipv6enabled = false;
118
0
                } else if (c == '6') {
119
0
                    *ipv6enabled = true;
120
0
                } else {
121
0
                    printf("Invalid argument: %s. Try --ipv4 or --ipv6!\n", argv[argi]);
122
0
                    return -1;
123
0
                }
124
0
            } else {
125
0
                printf("Invalid argument: %s. Try --ipv4 or --ipv6!\n", argv[argi]);
126
0
                return -1;
127
0
            }
128
129
0
            if (argvoffset != argi - 1) {
130
0
                printf("Argument must come first: %s.\n", argv[argi]);
131
0
                return -1;
132
0
            }
133
134
0
            argvoffset++;
135
0
        }
136
0
    }
137
138
0
    return argvoffset;
139
0
}
140
141
142
static const char *test_rng_name(void)
143
0
{
144
0
    return "test_rng";
145
0
}
146
147
static uint32_t rng_state;
148
149
static uint32_t test_rng_random(void)
150
0
{
151
0
    rng_state = 2624534371 * rng_state + 1;
152
0
    return rng_state;
153
0
}
154
155
static void test_rng_buf(void *const buf, const size_t size)
156
0
{
157
0
    uint8_t *p = (uint8_t *)buf;
158
0
    uint32_t r = 0;
159
160
0
    for (size_t i = 0; i < size; i++) {
161
0
        if ((i % 4) == 0) {
162
0
            r = test_rng_random();
163
0
        }
164
165
0
        *p = (r >> ((i % 4) * 8)) & 0xff;
166
0
        ++p;
167
0
    }
168
0
}
169
170
static uint32_t test_rng_uniform(const uint32_t upper_bound)
171
0
{
172
    // XXX: Not uniform! But that's ok for testing purposes.
173
0
    return test_rng_random() % upper_bound;
174
0
}
175
176
0
static void test_rng_stir(void) { }
177
static int test_rng_close(void)
178
0
{
179
0
    return 0;
180
0
}
181
182
static randombytes_implementation test_rng = {
183
    test_rng_name,
184
    test_rng_random,
185
    test_rng_stir,
186
    test_rng_uniform,
187
    test_rng_buf,
188
    test_rng_close
189
};
190
191
/* Simple insecure PRNG for testing purposes */
192
int use_test_rng(uint32_t seed)
193
0
{
194
0
    rng_state = seed;
195
196
0
    return randombytes_set_implementation(&test_rng);
197
0
}