├── .all-contributorsrc ├── .github ├── FUNDING.yml └── workflows │ ├── FUNDING.yml │ ├── greet.yml │ └── test.yml ├── .whitesource ├── CppCheckReport.txt ├── Dockerfile ├── LICENSE ├── README.md ├── __tests__ ├── client │ └── client.c ├── exclude │ └── perfect_square.c ├── fibonacci.c ├── server │ └── server.c └── test.c ├── action.yml ├── cppcheck_report.txt ├── report.txt └── src └── entrypoint.py /.all-contributorsrc: -------------------------------------------------------------------------------- 1 | { 2 | "files": [ 3 | "README.md" 4 | ], 5 | "imageSize": 100, 6 | "commit": false, 7 | "contributors": [ 8 | { 9 | "login": "BaderEddineOuaich", 10 | "name": "Bader", 11 | "avatar_url": "https://avatars2.githubusercontent.com/u/49657842?v=4", 12 | "profile": "http://badereddineouaich.herokuapp.com", 13 | "contributions": [ 14 | "test" 15 | ] 16 | }, 17 | { 18 | "login": "sthagen", 19 | "name": "Stefan Hagen", 20 | "avatar_url": "https://avatars1.githubusercontent.com/u/450800?v=4", 21 | "profile": "https://stefan-hagen.website", 22 | "contributions": [ 23 | "infra", 24 | "test", 25 | "code" 26 | ] 27 | } 28 | ], 29 | "contributorsPerLine": 7, 30 | "projectName": "cppcheck-action", 31 | "projectOwner": "deep5050", 32 | "repoType": "github", 33 | "repoHost": "https://github.com", 34 | "skipCi": true 35 | } 36 | -------------------------------------------------------------------------------- /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | # These are supported funding model platforms 2 | 3 | github: deep5050 4 | patreon: # Replace with a single Patreon username 5 | open_collective: # Replace with a single Open Collective username 6 | ko_fi: # Replace with a single Ko-fi username 7 | tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel 8 | community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry 9 | liberapay: # Replace with a single Liberapay username 10 | issuehunt: # Replace with a single IssueHunt username 11 | otechie: # Replace with a single Otechie username 12 | lfx_crowdfunding: # Replace with a single LFX Crowdfunding project-name e.g., cloud-foundry 13 | custom: "https://www.paypal.com/paypalme/deep5050" 14 | -------------------------------------------------------------------------------- /.github/workflows/FUNDING.yml: -------------------------------------------------------------------------------- 1 | github: deep5050 2 | custom: ["https://www.paypal.com/paypalme/deep5050"] 3 | -------------------------------------------------------------------------------- /.github/workflows/greet.yml: -------------------------------------------------------------------------------- 1 | name: "Greet With A Random Meme" 2 | on: 3 | issues: 4 | types: [opened, reopened] 5 | pull_request_target: 6 | types: [opened, reopened] 7 | 8 | 9 | jobs: 10 | test: 11 | name: setup environment 12 | runs-on: ubuntu-latest 13 | steps: 14 | - name: memes on isssues 15 | uses: deep5050/memes-on-issues-action@main 16 | with: 17 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 18 | -------------------------------------------------------------------------------- /.github/workflows/test.yml: -------------------------------------------------------------------------------- 1 | name: cppcheck-action-other_options-test 2 | 3 | on: 4 | push: 5 | branches: [ main ] 6 | pull_request: 7 | branches: [ main ] 8 | 9 | jobs: 10 | build: 11 | name: cppcheck 12 | runs-on: ubuntu-latest 13 | steps: 14 | - uses: actions/checkout@v2 15 | 16 | # CppCheck analysis task 17 | - name: cppcheck 18 | uses: ./ 19 | with: 20 | github_token: ${{ secrets.GITHUB_TOKEN }} 21 | check_library: disable 22 | skip_preprocessor: disable 23 | enable: all #performance,portability,warning 24 | exclude_check: ./__tests__/exclude/ 25 | inconclusive: disable 26 | inline_suppression: disable 27 | force_language: c 28 | force: enable 29 | max_ctu_depth: 12 30 | platform: disable 31 | #std: c11 32 | output_file: ./CppCheckReport.txt 33 | other_options: --bug-hunting --verbose --std=c11 34 | 35 | # Report generating task 36 | - name: publish report 37 | uses: mikeal/publish-to-github-action@master 38 | env: 39 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 40 | BRANCH_NAME: 'main' # your branch name goes here 41 | -------------------------------------------------------------------------------- /.whitesource: -------------------------------------------------------------------------------- 1 | { 2 | "checkRunSettings": { 3 | "vulnerableCheckRunConclusionLevel": "failure" 4 | }, 5 | "issueSettings": { 6 | "minSeverityLevel": "LOW" 7 | } 8 | } -------------------------------------------------------------------------------- /CppCheckReport.txt: -------------------------------------------------------------------------------- 1 | __tests__/client/client.c:58:11: error: Buffer read/write, when calling 'memset' it cannot be determined that 1st argument is not overflowed [bughuntingBufferOverflow] 2 | memset(name, '\0', MAX_USERNAME_LEN); 3 | ^ 4 | __tests__/client/client.c:61:12: error: Buffer read/write, when calling 'strncpy' it cannot be determined that 1st argument is not overflowed [bughuntingBufferOverflow] 5 | strncpy(name, p_args->name, strlen(p_args->name) + 1); 6 | ^ 7 | __tests__/client/client.c:65:15: error: Buffer read/write, when calling 'memset' it cannot be determined that 1st argument is not overflowed [bughuntingBufferOverflow] 8 | memset(rcvd_msg, '\0', MAX_MSG_LEN); 9 | ^ 10 | __tests__/client/client.c:96:11: error: Buffer read/write, when calling 'memset' it cannot be determined that 1st argument is not overflowed [bughuntingBufferOverflow] 11 | memset(&server_addr, 0, sizeof(server_addr)); 12 | ^ 13 | __tests__/client/client.c:97:11: error: Buffer read/write, when calling 'memset' it cannot be determined that 1st argument is not overflowed [bughuntingBufferOverflow] 14 | memset(server_ip, '\0', sizeof(server_ip)); 15 | ^ 16 | __tests__/client/client.c:99:11: error: Buffer read/write, when calling 'memset' it cannot be determined that 1st argument is not overflowed [bughuntingBufferOverflow] 17 | memset(name, '\0', sizeof(name)); 18 | ^ 19 | __tests__/client/client.c:100:11: error: Buffer read/write, when calling 'memset' it cannot be determined that 1st argument is not overflowed [bughuntingBufferOverflow] 20 | memset(buff, '\0', sizeof(buff)); 21 | ^ 22 | __tests__/client/client.c:102:32: error: Cannot determine that 'argv[0]' is initialized (you can use 'const' to say data must be initialized) [bughuntingUninitNonConstArg] 23 | while ((opt = getopt(argc, argv, "-a:p:D:n:")) != -1) 24 | ^ 25 | __tests__/client/client.c:162:15: error: Buffer read/write, when calling 'strcpy' it cannot be determined that 1st argument is not overflowed [bughuntingBufferOverflow] 26 | strcpy(server_ip, "0.0.0.0"); 27 | ^ 28 | __tests__/client/client.c:233:12: error: Buffer read/write, when calling 'strncpy' it cannot be determined that 1st argument is not overflowed [bughuntingBufferOverflow] 29 | strncpy(thread_args.name, name, strlen(name)); 30 | ^ 31 | __tests__/client/client.c:223:31: error: Cannot determine that 'greetings_from_server[0]' is initialized [bughuntingUninit] 32 | LOG(_LOG_INFO_, "%s", greetings_from_server); 33 | ^ 34 | __tests__/server/server.c:32:54: error: Array index out of bounds, cannot determine that i is less than 20 [bughuntingArrayIndexOutOfBounds] 35 | int return_val = pthread_cancel(threads_pool[i]); 36 | ^ 37 | __tests__/server/server.c:32:54: error: Array index out of bounds, cannot determine that i is not negative [bughuntingArrayIndexNegative] 38 | int return_val = pthread_cancel(threads_pool[i]); 39 | ^ 40 | __tests__/server/server.c:32:54: error: Array index out of bounds, cannot determine that i is less than 20 [bughuntingArrayIndexOutOfBounds] 41 | int return_val = pthread_cancel(threads_pool[i]); 42 | ^ 43 | __tests__/server/server.c:45:21: note: Calling kill_all_threads 44 | kill_all_threads(); 45 | ^ 46 | __tests__/server/server.c:32:54: note: Array index out of bounds, cannot determine that i is less than 20 47 | int return_val = pthread_cancel(threads_pool[i]); 48 | ^ 49 | __tests__/server/server.c:32:54: error: Array index out of bounds, cannot determine that i is not negative [bughuntingArrayIndexNegative] 50 | int return_val = pthread_cancel(threads_pool[i]); 51 | ^ 52 | __tests__/server/server.c:45:21: note: Calling kill_all_threads 53 | kill_all_threads(); 54 | ^ 55 | __tests__/server/server.c:32:54: note: Array index out of bounds, cannot determine that i is not negative 56 | int return_val = pthread_cancel(threads_pool[i]); 57 | ^ 58 | __tests__/server/server.c:62:32: error: Cannot determine that 'argv[0]' is initialized (you can use 'const' to say data must be initialized) [bughuntingUninitNonConstArg] 59 | while ((opt = getopt(argc, argv, "-p:b:D:")) != -1) 60 | ^ 61 | __tests__/server/server.c:126:11: error: Buffer read/write, when calling 'memset' it cannot be determined that 1st argument is not overflowed [bughuntingBufferOverflow] 62 | memset(&thread_args, 0, sizeof(thread_args)); 63 | ^ 64 | __tests__/server/server.c:132:11: error: Buffer read/write, when calling 'memset' it cannot be determined that 1st argument is not overflowed [bughuntingBufferOverflow] 65 | memset(&server_addr, 0, sizeof(server_addr)); 66 | ^ 67 | __tests__/server/server.c:133:11: error: Buffer read/write, when calling 'memset' it cannot be determined that 1st argument is not overflowed [bughuntingBufferOverflow] 68 | memset(&client_addr, 0, sizeof(client_addr)); 69 | ^ 70 | __tests__/server/server.c:148:14: error: Cannot determine that 'results' is initialized [bughuntingUninit] 71 | for (p = results; p != NULL; p = p->ai_next) 72 | ^ 73 | __tests__/server/server.c:148:12: error: Cannot determine that 'p=results' is initialized [bughuntingUninit] 74 | for (p = results; p != NULL; p = p->ai_next) 75 | ^ 76 | __tests__/server/server.c:148:23: error: Cannot determine that 'p' is initialized [bughuntingUninit] 77 | for (p = results; p != NULL; p = p->ai_next) 78 | ^ 79 | __tests__/server/server.c:84:19: error: Buffer read/write, when calling 'memset' it cannot be determined that 1st argument is not overflowed [bughuntingBufferOverflow] 80 | memset(temp, '\0', sizeof(temp)); 81 | ^ 82 | __tests__/server/server.c:85:20: error: Buffer read/write, when calling 'strncpy' it cannot be determined that 1st argument is not overflowed [bughuntingBufferOverflow] 83 | strncpy(temp, optarg, 4); 84 | ^ 85 | __tests__/server/server.c:174:45: error: Cannot determine that 'addr' is initialized [bughuntingUninit] 86 | inet_ntop(p->ai_family, p->ai_addr, addr, sizeof(addr)); 87 | ^ 88 | __tests__/server/server.c:178:18: error: Cannot determine that 'results' is initialized [bughuntingUninit] 89 | freeaddrinfo(results); 90 | ^ 91 | __tests__/server/server.c:191:39: error: Cannot determine that 'backlog' is initialized [bughuntingUninit] 92 | listen_status = listen(server_fd, backlog); 93 | ^ 94 | __tests__/server/server.c:199:66: error: Cannot determine that 'addr' is initialized [bughuntingUninit] 95 | LOG(_LOG_INFO_, "UP and LISTENING on %s:%s with BACKLOG %d", addr, port, backlog); 96 | ^ 97 | __tests__/server/server.c:199:72: error: Cannot determine that 'port' is initialized [bughuntingUninit] 98 | LOG(_LOG_INFO_, "UP and LISTENING on %s:%s with BACKLOG %d", addr, port, backlog); 99 | ^ 100 | __tests__/server/server.c:199:78: error: Cannot determine that 'backlog' is initialized [bughuntingUninit] 101 | LOG(_LOG_INFO_, "UP and LISTENING on %s:%s with BACKLOG %d", addr, port, backlog); 102 | ^ 103 | __tests__/server/server.c:210:73: error: Cannot determine that 'addr' is initialized [bughuntingUninit] 104 | inet_ntop(client_addr.sin_family, &client_addr.sin_addr.s_addr, addr, sizeof(addr)); 105 | ^ 106 | __tests__/server/server.c:212:59: error: Cannot determine that 'client_addr' is initialized [bughuntingUninit] 107 | client_fd = accept(server_fd, (struct sockaddr *)&client_addr, &client_addr_size); 108 | ^ 109 | __tests__/server/server.c:220:65: error: Cannot determine that 'addr' is initialized [bughuntingUninit] 110 | LOG(_LOG_INFO_, "NEW CLIENT: ID(%d): %s:%d", client_fd, addr, ntohs(client_addr.sin_port)); 111 | ^ 112 | __tests__/server/server.c:228:29: error: Cannot determine that 't_id' is initialized [bughuntingUninit] 113 | if (pthread_create(&t_id, NULL, service_clients, (void *)&thread_args) != 0) 114 | ^ 115 | __tests__/server/server.c:228:67: error: Cannot determine that 'thread_args' is initialized [bughuntingUninit] 116 | if (pthread_create(&t_id, NULL, service_clients, (void *)&thread_args) != 0) 117 | ^ 118 | __tests__/server/server.c:230:64: error: Cannot determine that 't_id' is initialized [bughuntingUninit] 119 | LOG(_LOG_ERR_, "couldn't create the Thread %ld\n", t_id); 120 | ^ 121 | __tests__/server/server.c:236:76: error: Cannot determine that 't_id' is initialized [bughuntingUninit] 122 | LOG(_LOG_INFO_, "New thread created: %ld to service client ID %d", t_id, client_fd); 123 | ^ 124 | __tests__/server/server.c:237:24: error: Cannot determine that 't_id' is initialized [bughuntingUninit] 125 | pthread_detach(t_id); 126 | ^ 127 | __tests__/server/server.c:238:40: error: Cannot determine that 't_id' is initialized [bughuntingUninit] 128 | threads_pool[++thread_count] = t_id; 129 | ^ 130 | __tests__/test.c:26:17: error: There is function call, cannot determine that 1st argument is initialized. [bughuntingUninitArg] 131 | str = asctime(local); 132 | ^ 133 | __tests__/test.c:29:20: error: There is function call, cannot determine that 1st argument is initialized. [bughuntingUninitArg] 134 | int len = strlen(str) + 1; 135 | ^ 136 | __tests__/test.c:34:41: error: There is function call, cannot determine that 3rd argument value is valid. Bad value: less than 0 [bughuntingInvalidArgValue] 137 | strncpy(&str[i], &str[i + 1], len - i); 138 | ^ 139 | __tests__/test.c:34:14: error: Buffer read/write, when calling 'strncpy' it cannot be determined that 1st argument is not overflowed [bughuntingBufferOverflow] 140 | strncpy(&str[i], &str[i + 1], len - i); 141 | ^ 142 | __tests__/test.c:26:17: error: There is function call, cannot determine that 1st argument is initialized. [bughuntingUninitArg] 143 | str = asctime(local); 144 | ^ 145 | __tests__/test.c:136:45: note: Calling timestamp 146 | printf("\n[%s] SERVER CLOSED\n", timestamp()); 147 | ^ 148 | __tests__/test.c:26:17: note: There is function call, cannot determine that 1st argument is initialized. 149 | str = asctime(local); 150 | ^ 151 | __tests__/test.c:29:20: error: There is function call, cannot determine that 1st argument is initialized. [bughuntingUninitArg] 152 | int len = strlen(str) + 1; 153 | ^ 154 | __tests__/test.c:136:45: note: Calling timestamp 155 | printf("\n[%s] SERVER CLOSED\n", timestamp()); 156 | ^ 157 | __tests__/test.c:29:20: note: There is function call, cannot determine that 1st argument is initialized. 158 | int len = strlen(str) + 1; 159 | ^ 160 | __tests__/test.c:34:41: error: There is function call, cannot determine that 3rd argument value is valid. Bad value: less than 0 [bughuntingInvalidArgValue] 161 | strncpy(&str[i], &str[i + 1], len - i); 162 | ^ 163 | __tests__/test.c:136:45: note: Calling timestamp 164 | printf("\n[%s] SERVER CLOSED\n", timestamp()); 165 | ^ 166 | __tests__/test.c:34:41: note: There is function call, cannot determine that 3rd argument value is valid. Bad value: less than 0 167 | strncpy(&str[i], &str[i + 1], len - i); 168 | ^ 169 | __tests__/test.c:34:14: error: Buffer read/write, when calling 'strncpy' it cannot be determined that 1st argument is not overflowed [bughuntingBufferOverflow] 170 | strncpy(&str[i], &str[i + 1], len - i); 171 | ^ 172 | __tests__/test.c:136:45: note: Calling timestamp 173 | printf("\n[%s] SERVER CLOSED\n", timestamp()); 174 | ^ 175 | __tests__/test.c:34:14: note: Buffer read/write, when calling 'strncpy' it cannot be determined that 1st argument is not overflowed 176 | strncpy(&str[i], &str[i + 1], len - i); 177 | ^ 178 | __tests__/test.c:148:11: error: Cannot determine that 'argv[1]' is initialized (you can use 'const' to say data must be initialized) [bughuntingUninitNonConstArg] 179 | if (argv[1] == "" || argv[1] == NULL) { 180 | ^ 181 | __tests__/test.c:153:11: error: Cannot determine that 'argv[2]' is initialized (you can use 'const' to say data must be initialized) [bughuntingUninitNonConstArg] 182 | if (argv[2] == "" || argv[2] == NULL) { 183 | ^ 184 | __tests__/test.c:158:24: error: Cannot determine that 'argv[2]' is initialized (you can use 'const' to say data must be initialized) [bughuntingUninitNonConstArg] 185 | backlog = strtol(argv[2], &strptr, 10); 186 | ^ 187 | __tests__/test.c:172:9: error: Buffer read/write, when calling 'memset' it cannot be determined that 1st argument is not overflowed [bughuntingBufferOverflow] 188 | memset(&server_addr, 0, sizeof(server_addr)); 189 | ^ 190 | __tests__/test.c:173:9: error: Buffer read/write, when calling 'memset' it cannot be determined that 1st argument is not overflowed [bughuntingBufferOverflow] 191 | memset(&client_addr, 0, sizeof(client_addr)); 192 | ^ 193 | __tests__/test.c:194:44: error: Cannot determine that 'argv[1]' is initialized (you can use 'const' to say data must be initialized) [bughuntingUninitNonConstArg] 194 | if ((addr_status = getaddrinfo(NULL, argv[1], &server_addr, &results)) != 0) { 195 | ^ 196 | __tests__/test.c:26:17: error: There is function call, cannot determine that 1st argument is initialized. [bughuntingUninitArg] 197 | str = asctime(local); 198 | ^ 199 | __tests__/test.c:195:63: note: Calling timestamp 200 | printf("[%s] SERVER: ERROR getaddrinfo(): %s\n", timestamp(), 201 | ^ 202 | __tests__/test.c:26:17: note: There is function call, cannot determine that 1st argument is initialized. 203 | str = asctime(local); 204 | ^ 205 | __tests__/test.c:29:20: error: There is function call, cannot determine that 1st argument is initialized. [bughuntingUninitArg] 206 | int len = strlen(str) + 1; 207 | ^ 208 | __tests__/test.c:195:63: note: Calling timestamp 209 | printf("[%s] SERVER: ERROR getaddrinfo(): %s\n", timestamp(), 210 | ^ 211 | __tests__/test.c:29:20: note: There is function call, cannot determine that 1st argument is initialized. 212 | int len = strlen(str) + 1; 213 | ^ 214 | __tests__/test.c:34:41: error: There is function call, cannot determine that 3rd argument value is valid. Bad value: less than 0 [bughuntingInvalidArgValue] 215 | strncpy(&str[i], &str[i + 1], len - i); 216 | ^ 217 | __tests__/test.c:195:63: note: Calling timestamp 218 | printf("[%s] SERVER: ERROR getaddrinfo(): %s\n", timestamp(), 219 | ^ 220 | __tests__/test.c:34:41: note: There is function call, cannot determine that 3rd argument value is valid. Bad value: less than 0 221 | strncpy(&str[i], &str[i + 1], len - i); 222 | ^ 223 | __tests__/test.c:34:14: error: Buffer read/write, when calling 'strncpy' it cannot be determined that 1st argument is not overflowed [bughuntingBufferOverflow] 224 | strncpy(&str[i], &str[i + 1], len - i); 225 | ^ 226 | __tests__/test.c:195:63: note: Calling timestamp 227 | printf("[%s] SERVER: ERROR getaddrinfo(): %s\n", timestamp(), 228 | ^ 229 | __tests__/test.c:34:14: note: Buffer read/write, when calling 'strncpy' it cannot be determined that 1st argument is not overflowed 230 | strncpy(&str[i], &str[i + 1], len - i); 231 | ^ 232 | __tests__/test.c:201:12: error: Cannot determine that 'results' is initialized [bughuntingUninit] 233 | for (p = results; p != NULL; p = p->ai_next) { 234 | ^ 235 | __tests__/test.c:201:10: error: Cannot determine that 'p=results' is initialized [bughuntingUninit] 236 | for (p = results; p != NULL; p = p->ai_next) { 237 | ^ 238 | __tests__/test.c:201:21: error: Cannot determine that 'p' is initialized [bughuntingUninit] 239 | for (p = results; p != NULL; p = p->ai_next) { 240 | ^ 241 | __tests__/test.c:203:41: error: Cannot determine that 'addr[0]' is initialized [bughuntingUninit] 242 | inet_ntop(p->ai_family, p->ai_addr, addr, sizeof(addr)); 243 | ^ 244 | __tests__/test.c:26:17: error: There is function call, cannot determine that 1st argument is initialized. [bughuntingUninitArg] 245 | str = asctime(local); 246 | ^ 247 | __tests__/test.c:204:60: note: Calling timestamp 248 | printf("[%s] SERVER: Trying to build on: %s", timestamp(), addr); 249 | ^ 250 | __tests__/test.c:26:17: note: There is function call, cannot determine that 1st argument is initialized. 251 | str = asctime(local); 252 | ^ 253 | __tests__/test.c:29:20: error: There is function call, cannot determine that 1st argument is initialized. [bughuntingUninitArg] 254 | int len = strlen(str) + 1; 255 | ^ 256 | __tests__/test.c:204:60: note: Calling timestamp 257 | printf("[%s] SERVER: Trying to build on: %s", timestamp(), addr); 258 | ^ 259 | __tests__/test.c:29:20: note: There is function call, cannot determine that 1st argument is initialized. 260 | int len = strlen(str) + 1; 261 | ^ 262 | __tests__/test.c:34:41: error: There is function call, cannot determine that 3rd argument value is valid. Bad value: less than 0 [bughuntingInvalidArgValue] 263 | strncpy(&str[i], &str[i + 1], len - i); 264 | ^ 265 | __tests__/test.c:204:60: note: Calling timestamp 266 | printf("[%s] SERVER: Trying to build on: %s", timestamp(), addr); 267 | ^ 268 | __tests__/test.c:34:41: note: There is function call, cannot determine that 3rd argument value is valid. Bad value: less than 0 269 | strncpy(&str[i], &str[i + 1], len - i); 270 | ^ 271 | __tests__/test.c:34:14: error: Buffer read/write, when calling 'strncpy' it cannot be determined that 1st argument is not overflowed [bughuntingBufferOverflow] 272 | strncpy(&str[i], &str[i + 1], len - i); 273 | ^ 274 | __tests__/test.c:204:60: note: Calling timestamp 275 | printf("[%s] SERVER: Trying to build on: %s", timestamp(), addr); 276 | ^ 277 | __tests__/test.c:34:14: note: Buffer read/write, when calling 'strncpy' it cannot be determined that 1st argument is not overflowed 278 | strncpy(&str[i], &str[i + 1], len - i); 279 | ^ 280 | __tests__/test.c:231:16: error: Cannot determine that 'results' is initialized [bughuntingUninit] 281 | freeaddrinfo(results); 282 | ^ 283 | __tests__/test.c:26:17: error: There is function call, cannot determine that 1st argument is initialized. [bughuntingUninitArg] 284 | str = asctime(local); 285 | ^ 286 | __tests__/test.c:250:19: note: Calling timestamp 287 | timestamp(), addr, argv[1], backlog); 288 | ^ 289 | __tests__/test.c:26:17: note: There is function call, cannot determine that 1st argument is initialized. 290 | str = asctime(local); 291 | ^ 292 | __tests__/test.c:29:20: error: There is function call, cannot determine that 1st argument is initialized. [bughuntingUninitArg] 293 | int len = strlen(str) + 1; 294 | ^ 295 | __tests__/test.c:250:19: note: Calling timestamp 296 | timestamp(), addr, argv[1], backlog); 297 | ^ 298 | __tests__/test.c:29:20: note: There is function call, cannot determine that 1st argument is initialized. 299 | int len = strlen(str) + 1; 300 | ^ 301 | __tests__/test.c:34:41: error: There is function call, cannot determine that 3rd argument value is valid. Bad value: less than 0 [bughuntingInvalidArgValue] 302 | strncpy(&str[i], &str[i + 1], len - i); 303 | ^ 304 | __tests__/test.c:250:19: note: Calling timestamp 305 | timestamp(), addr, argv[1], backlog); 306 | ^ 307 | __tests__/test.c:34:41: note: There is function call, cannot determine that 3rd argument value is valid. Bad value: less than 0 308 | strncpy(&str[i], &str[i + 1], len - i); 309 | ^ 310 | __tests__/test.c:34:14: error: Buffer read/write, when calling 'strncpy' it cannot be determined that 1st argument is not overflowed [bughuntingBufferOverflow] 311 | strncpy(&str[i], &str[i + 1], len - i); 312 | ^ 313 | __tests__/test.c:250:19: note: Calling timestamp 314 | timestamp(), addr, argv[1], backlog); 315 | ^ 316 | __tests__/test.c:34:14: note: Buffer read/write, when calling 'strncpy' it cannot be determined that 1st argument is not overflowed 317 | strncpy(&str[i], &str[i + 1], len - i); 318 | ^ 319 | __tests__/test.c:250:33: error: Cannot determine that 'argv[1]' is initialized (you can use 'const' to say data must be initialized) [bughuntingUninitNonConstArg] 320 | timestamp(), addr, argv[1], backlog); 321 | ^ 322 | __tests__/test.c:26:17: error: There is function call, cannot determine that 1st argument is initialized. [bughuntingUninitArg] 323 | str = asctime(local); 324 | ^ 325 | __tests__/test.c:279:64: note: Calling timestamp 326 | printf("[%s] SERVER: NEW CLIENT ID(%d): %s:%d\n", timestamp(), 327 | ^ 328 | __tests__/test.c:26:17: note: There is function call, cannot determine that 1st argument is initialized. 329 | str = asctime(local); 330 | ^ 331 | __tests__/test.c:29:20: error: There is function call, cannot determine that 1st argument is initialized. [bughuntingUninitArg] 332 | int len = strlen(str) + 1; 333 | ^ 334 | __tests__/test.c:279:64: note: Calling timestamp 335 | printf("[%s] SERVER: NEW CLIENT ID(%d): %s:%d\n", timestamp(), 336 | ^ 337 | __tests__/test.c:29:20: note: There is function call, cannot determine that 1st argument is initialized. 338 | int len = strlen(str) + 1; 339 | ^ 340 | __tests__/test.c:34:41: error: There is function call, cannot determine that 3rd argument value is valid. Bad value: less than 0 [bughuntingInvalidArgValue] 341 | strncpy(&str[i], &str[i + 1], len - i); 342 | ^ 343 | __tests__/test.c:279:64: note: Calling timestamp 344 | printf("[%s] SERVER: NEW CLIENT ID(%d): %s:%d\n", timestamp(), 345 | ^ 346 | __tests__/test.c:34:41: note: There is function call, cannot determine that 3rd argument value is valid. Bad value: less than 0 347 | strncpy(&str[i], &str[i + 1], len - i); 348 | ^ 349 | __tests__/test.c:34:14: error: Buffer read/write, when calling 'strncpy' it cannot be determined that 1st argument is not overflowed [bughuntingBufferOverflow] 350 | strncpy(&str[i], &str[i + 1], len - i); 351 | ^ 352 | __tests__/test.c:279:64: note: Calling timestamp 353 | printf("[%s] SERVER: NEW CLIENT ID(%d): %s:%d\n", timestamp(), 354 | ^ 355 | __tests__/test.c:34:14: note: Buffer read/write, when calling 'strncpy' it cannot be determined that 1st argument is not overflowed 356 | strncpy(&str[i], &str[i + 1], len - i); 357 | ^ 358 | __tests__/test.c:26:17: error: There is function call, cannot determine that 1st argument is initialized. [bughuntingUninitArg] 359 | str = asctime(local); 360 | ^ 361 | __tests__/test.c:287:75: note: Calling timestamp 362 | printf("[%s] SERVER: Connection lost with client(%d)\n", timestamp(), 363 | ^ 364 | __tests__/test.c:26:17: note: There is function call, cannot determine that 1st argument is initialized. 365 | str = asctime(local); 366 | ^ 367 | __tests__/test.c:29:20: error: There is function call, cannot determine that 1st argument is initialized. [bughuntingUninitArg] 368 | int len = strlen(str) + 1; 369 | ^ 370 | __tests__/test.c:287:75: note: Calling timestamp 371 | printf("[%s] SERVER: Connection lost with client(%d)\n", timestamp(), 372 | ^ 373 | __tests__/test.c:29:20: note: There is function call, cannot determine that 1st argument is initialized. 374 | int len = strlen(str) + 1; 375 | ^ 376 | __tests__/test.c:34:41: error: There is function call, cannot determine that 3rd argument value is valid. Bad value: less than 0 [bughuntingInvalidArgValue] 377 | strncpy(&str[i], &str[i + 1], len - i); 378 | ^ 379 | __tests__/test.c:287:75: note: Calling timestamp 380 | printf("[%s] SERVER: Connection lost with client(%d)\n", timestamp(), 381 | ^ 382 | __tests__/test.c:34:41: note: There is function call, cannot determine that 3rd argument value is valid. Bad value: less than 0 383 | strncpy(&str[i], &str[i + 1], len - i); 384 | ^ 385 | __tests__/test.c:34:14: error: Buffer read/write, when calling 'strncpy' it cannot be determined that 1st argument is not overflowed [bughuntingBufferOverflow] 386 | strncpy(&str[i], &str[i + 1], len - i); 387 | ^ 388 | __tests__/test.c:287:75: note: Calling timestamp 389 | printf("[%s] SERVER: Connection lost with client(%d)\n", timestamp(), 390 | ^ 391 | __tests__/test.c:34:14: note: Buffer read/write, when calling 'strncpy' it cannot be determined that 1st argument is not overflowed 392 | strncpy(&str[i], &str[i + 1], len - i); 393 | ^ 394 | __tests__/test.c:296:13: error: Cannot determine that 'buff[0]' is initialized [bughuntingUninit] 395 | bzero(buff, max_mssg_len); 396 | ^ 397 | __tests__/test.c:26:17: error: There is function call, cannot determine that 1st argument is initialized. [bughuntingUninitArg] 398 | str = asctime(local); 399 | ^ 400 | __tests__/test.c:303:77: note: Calling timestamp 401 | printf("[%s] SERVER: Connection lost with client(%d)\n", timestamp(), 402 | ^ 403 | __tests__/test.c:26:17: note: There is function call, cannot determine that 1st argument is initialized. 404 | str = asctime(local); 405 | ^ 406 | __tests__/test.c:29:20: error: There is function call, cannot determine that 1st argument is initialized. [bughuntingUninitArg] 407 | int len = strlen(str) + 1; 408 | ^ 409 | __tests__/test.c:303:77: note: Calling timestamp 410 | printf("[%s] SERVER: Connection lost with client(%d)\n", timestamp(), 411 | ^ 412 | __tests__/test.c:29:20: note: There is function call, cannot determine that 1st argument is initialized. 413 | int len = strlen(str) + 1; 414 | ^ 415 | __tests__/test.c:34:41: error: There is function call, cannot determine that 3rd argument value is valid. Bad value: less than 0 [bughuntingInvalidArgValue] 416 | strncpy(&str[i], &str[i + 1], len - i); 417 | ^ 418 | __tests__/test.c:303:77: note: Calling timestamp 419 | printf("[%s] SERVER: Connection lost with client(%d)\n", timestamp(), 420 | ^ 421 | __tests__/test.c:34:41: note: There is function call, cannot determine that 3rd argument value is valid. Bad value: less than 0 422 | strncpy(&str[i], &str[i + 1], len - i); 423 | ^ 424 | __tests__/test.c:34:14: error: Buffer read/write, when calling 'strncpy' it cannot be determined that 1st argument is not overflowed [bughuntingBufferOverflow] 425 | strncpy(&str[i], &str[i + 1], len - i); 426 | ^ 427 | __tests__/test.c:303:77: note: Calling timestamp 428 | printf("[%s] SERVER: Connection lost with client(%d)\n", timestamp(), 429 | ^ 430 | __tests__/test.c:34:14: note: Buffer read/write, when calling 'strncpy' it cannot be determined that 1st argument is not overflowed 431 | strncpy(&str[i], &str[i + 1], len - i); 432 | ^ 433 | __tests__/test.c:26:17: error: There is function call, cannot determine that 1st argument is initialized. [bughuntingUninitArg] 434 | str = asctime(local); 435 | ^ 436 | __tests__/test.c:312:70: note: Calling timestamp 437 | printf("[%s] SERVER: DISCONNECTED: CLIENT(%d)\n", timestamp(), 438 | ^ 439 | __tests__/test.c:26:17: note: There is function call, cannot determine that 1st argument is initialized. 440 | str = asctime(local); 441 | ^ 442 | __tests__/test.c:29:20: error: There is function call, cannot determine that 1st argument is initialized. [bughuntingUninitArg] 443 | int len = strlen(str) + 1; 444 | ^ 445 | __tests__/test.c:312:70: note: Calling timestamp 446 | printf("[%s] SERVER: DISCONNECTED: CLIENT(%d)\n", timestamp(), 447 | ^ 448 | __tests__/test.c:29:20: note: There is function call, cannot determine that 1st argument is initialized. 449 | int len = strlen(str) + 1; 450 | ^ 451 | __tests__/test.c:34:41: error: There is function call, cannot determine that 3rd argument value is valid. Bad value: less than 0 [bughuntingInvalidArgValue] 452 | strncpy(&str[i], &str[i + 1], len - i); 453 | ^ 454 | __tests__/test.c:312:70: note: Calling timestamp 455 | printf("[%s] SERVER: DISCONNECTED: CLIENT(%d)\n", timestamp(), 456 | ^ 457 | __tests__/test.c:34:41: note: There is function call, cannot determine that 3rd argument value is valid. Bad value: less than 0 458 | strncpy(&str[i], &str[i + 1], len - i); 459 | ^ 460 | __tests__/test.c:34:14: error: Buffer read/write, when calling 'strncpy' it cannot be determined that 1st argument is not overflowed [bughuntingBufferOverflow] 461 | strncpy(&str[i], &str[i + 1], len - i); 462 | ^ 463 | __tests__/test.c:312:70: note: Calling timestamp 464 | printf("[%s] SERVER: DISCONNECTED: CLIENT(%d)\n", timestamp(), 465 | ^ 466 | __tests__/test.c:34:14: note: Buffer read/write, when calling 'strncpy' it cannot be determined that 1st argument is not overflowed 467 | strncpy(&str[i], &str[i + 1], len - i); 468 | ^ 469 | __tests__/test.c:26:17: error: There is function call, cannot determine that 1st argument is initialized. [bughuntingUninitArg] 470 | str = asctime(local); 471 | ^ 472 | __tests__/test.c:318:53: note: Calling timestamp 473 | printf("[%s] CLIENT_%d@host:~$%s", timestamp(), client_fd - 3, buff); 474 | ^ 475 | __tests__/test.c:26:17: note: There is function call, cannot determine that 1st argument is initialized. 476 | str = asctime(local); 477 | ^ 478 | __tests__/test.c:29:20: error: There is function call, cannot determine that 1st argument is initialized. [bughuntingUninitArg] 479 | int len = strlen(str) + 1; 480 | ^ 481 | __tests__/test.c:318:53: note: Calling timestamp 482 | printf("[%s] CLIENT_%d@host:~$%s", timestamp(), client_fd - 3, buff); 483 | ^ 484 | __tests__/test.c:29:20: note: There is function call, cannot determine that 1st argument is initialized. 485 | int len = strlen(str) + 1; 486 | ^ 487 | __tests__/test.c:34:41: error: There is function call, cannot determine that 3rd argument value is valid. Bad value: less than 0 [bughuntingInvalidArgValue] 488 | strncpy(&str[i], &str[i + 1], len - i); 489 | ^ 490 | __tests__/test.c:318:53: note: Calling timestamp 491 | printf("[%s] CLIENT_%d@host:~$%s", timestamp(), client_fd - 3, buff); 492 | ^ 493 | __tests__/test.c:34:41: note: There is function call, cannot determine that 3rd argument value is valid. Bad value: less than 0 494 | strncpy(&str[i], &str[i + 1], len - i); 495 | ^ 496 | __tests__/test.c:34:14: error: Buffer read/write, when calling 'strncpy' it cannot be determined that 1st argument is not overflowed [bughuntingBufferOverflow] 497 | strncpy(&str[i], &str[i + 1], len - i); 498 | ^ 499 | __tests__/test.c:318:53: note: Calling timestamp 500 | printf("[%s] CLIENT_%d@host:~$%s", timestamp(), client_fd - 3, buff); 501 | ^ 502 | __tests__/test.c:34:14: note: Buffer read/write, when calling 'strncpy' it cannot be determined that 1st argument is not overflowed 503 | strncpy(&str[i], &str[i + 1], len - i); 504 | ^ 505 | __tests__/test.c:62:50: error: Array index out of bounds, cannot determine that i is less than 20 [bughuntingArrayIndexOutOfBounds] 506 | int return_val = pthread_cancel(threads_pool[i]); 507 | ^ 508 | __tests__/test.c:62:50: error: Array index out of bounds, cannot determine that i is not negative [bughuntingArrayIndexNegative] 509 | int return_val = pthread_cancel(threads_pool[i]); 510 | ^ 511 | __tests__/test.c:26:17: error: There is function call, cannot determine that 1st argument is initialized. [bughuntingUninitArg] 512 | str = asctime(local); 513 | ^ 514 | __tests__/test.c:67:78: note: Calling timestamp 515 | printf("\n[%s] SERVER: %d threads did not shutdown properly\n", timestamp(), 516 | ^ 517 | __tests__/test.c:26:17: note: There is function call, cannot determine that 1st argument is initialized. 518 | str = asctime(local); 519 | ^ 520 | __tests__/test.c:29:20: error: There is function call, cannot determine that 1st argument is initialized. [bughuntingUninitArg] 521 | int len = strlen(str) + 1; 522 | ^ 523 | __tests__/test.c:67:78: note: Calling timestamp 524 | printf("\n[%s] SERVER: %d threads did not shutdown properly\n", timestamp(), 525 | ^ 526 | __tests__/test.c:29:20: note: There is function call, cannot determine that 1st argument is initialized. 527 | int len = strlen(str) + 1; 528 | ^ 529 | __tests__/test.c:34:41: error: There is function call, cannot determine that 3rd argument value is valid. Bad value: less than 0 [bughuntingInvalidArgValue] 530 | strncpy(&str[i], &str[i + 1], len - i); 531 | ^ 532 | __tests__/test.c:67:78: note: Calling timestamp 533 | printf("\n[%s] SERVER: %d threads did not shutdown properly\n", timestamp(), 534 | ^ 535 | __tests__/test.c:34:41: note: There is function call, cannot determine that 3rd argument value is valid. Bad value: less than 0 536 | strncpy(&str[i], &str[i + 1], len - i); 537 | ^ 538 | __tests__/test.c:34:14: error: Buffer read/write, when calling 'strncpy' it cannot be determined that 1st argument is not overflowed [bughuntingBufferOverflow] 539 | strncpy(&str[i], &str[i + 1], len - i); 540 | ^ 541 | __tests__/test.c:67:78: note: Calling timestamp 542 | printf("\n[%s] SERVER: %d threads did not shutdown properly\n", timestamp(), 543 | ^ 544 | __tests__/test.c:34:14: note: Buffer read/write, when calling 'strncpy' it cannot be determined that 1st argument is not overflowed 545 | strncpy(&str[i], &str[i + 1], len - i); 546 | ^ 547 | __tests__/test.c:26:17: error: There is function call, cannot determine that 1st argument is initialized. [bughuntingUninitArg] 548 | str = asctime(local); 549 | ^ 550 | __tests__/test.c:70:65: note: Calling timestamp 551 | printf("\n[%s] All threads exited successfully\n", timestamp()); 552 | ^ 553 | __tests__/test.c:26:17: note: There is function call, cannot determine that 1st argument is initialized. 554 | str = asctime(local); 555 | ^ 556 | __tests__/test.c:29:20: error: There is function call, cannot determine that 1st argument is initialized. [bughuntingUninitArg] 557 | int len = strlen(str) + 1; 558 | ^ 559 | __tests__/test.c:70:65: note: Calling timestamp 560 | printf("\n[%s] All threads exited successfully\n", timestamp()); 561 | ^ 562 | __tests__/test.c:29:20: note: There is function call, cannot determine that 1st argument is initialized. 563 | int len = strlen(str) + 1; 564 | ^ 565 | __tests__/test.c:34:41: error: There is function call, cannot determine that 3rd argument value is valid. Bad value: less than 0 [bughuntingInvalidArgValue] 566 | strncpy(&str[i], &str[i + 1], len - i); 567 | ^ 568 | __tests__/test.c:70:65: note: Calling timestamp 569 | printf("\n[%s] All threads exited successfully\n", timestamp()); 570 | ^ 571 | __tests__/test.c:34:41: note: There is function call, cannot determine that 3rd argument value is valid. Bad value: less than 0 572 | strncpy(&str[i], &str[i + 1], len - i); 573 | ^ 574 | __tests__/test.c:34:14: error: Buffer read/write, when calling 'strncpy' it cannot be determined that 1st argument is not overflowed [bughuntingBufferOverflow] 575 | strncpy(&str[i], &str[i + 1], len - i); 576 | ^ 577 | __tests__/test.c:70:65: note: Calling timestamp 578 | printf("\n[%s] All threads exited successfully\n", timestamp()); 579 | ^ 580 | __tests__/test.c:34:14: note: Buffer read/write, when calling 'strncpy' it cannot be determined that 1st argument is not overflowed 581 | strncpy(&str[i], &str[i + 1], len - i); 582 | ^ 583 | __tests__/test.c:26:17: error: There is function call, cannot determine that 1st argument is initialized. [bughuntingUninitArg] 584 | str = asctime(local); 585 | ^ 586 | __tests__/test.c:85:55: note: Calling timestamp 587 | printf("[%s] SERVER: Inside Thread %ld\n", timestamp(), pthread_self()); 588 | ^ 589 | __tests__/test.c:26:17: note: There is function call, cannot determine that 1st argument is initialized. 590 | str = asctime(local); 591 | ^ 592 | __tests__/test.c:29:20: error: There is function call, cannot determine that 1st argument is initialized. [bughuntingUninitArg] 593 | int len = strlen(str) + 1; 594 | ^ 595 | __tests__/test.c:85:55: note: Calling timestamp 596 | printf("[%s] SERVER: Inside Thread %ld\n", timestamp(), pthread_self()); 597 | ^ 598 | __tests__/test.c:29:20: note: There is function call, cannot determine that 1st argument is initialized. 599 | int len = strlen(str) + 1; 600 | ^ 601 | __tests__/test.c:34:41: error: There is function call, cannot determine that 3rd argument value is valid. Bad value: less than 0 [bughuntingInvalidArgValue] 602 | strncpy(&str[i], &str[i + 1], len - i); 603 | ^ 604 | __tests__/test.c:85:55: note: Calling timestamp 605 | printf("[%s] SERVER: Inside Thread %ld\n", timestamp(), pthread_self()); 606 | ^ 607 | __tests__/test.c:34:41: note: There is function call, cannot determine that 3rd argument value is valid. Bad value: less than 0 608 | strncpy(&str[i], &str[i + 1], len - i); 609 | ^ 610 | __tests__/test.c:34:14: error: Buffer read/write, when calling 'strncpy' it cannot be determined that 1st argument is not overflowed [bughuntingBufferOverflow] 611 | strncpy(&str[i], &str[i + 1], len - i); 612 | ^ 613 | __tests__/test.c:85:55: note: Calling timestamp 614 | printf("[%s] SERVER: Inside Thread %ld\n", timestamp(), pthread_self()); 615 | ^ 616 | __tests__/test.c:34:14: note: Buffer read/write, when calling 'strncpy' it cannot be determined that 1st argument is not overflowed 617 | strncpy(&str[i], &str[i + 1], len - i); 618 | ^ 619 | __tests__/test.c:26:17: error: There is function call, cannot determine that 1st argument is initialized. [bughuntingUninitArg] 620 | str = asctime(local); 621 | ^ 622 | __tests__/test.c:93:71: note: Calling timestamp 623 | printf("[%s] SERVER: Connection lost with client(%d)\n", timestamp(), 624 | ^ 625 | __tests__/test.c:26:17: note: There is function call, cannot determine that 1st argument is initialized. 626 | str = asctime(local); 627 | ^ 628 | __tests__/test.c:29:20: error: There is function call, cannot determine that 1st argument is initialized. [bughuntingUninitArg] 629 | int len = strlen(str) + 1; 630 | ^ 631 | __tests__/test.c:93:71: note: Calling timestamp 632 | printf("[%s] SERVER: Connection lost with client(%d)\n", timestamp(), 633 | ^ 634 | __tests__/test.c:29:20: note: There is function call, cannot determine that 1st argument is initialized. 635 | int len = strlen(str) + 1; 636 | ^ 637 | __tests__/test.c:34:41: error: There is function call, cannot determine that 3rd argument value is valid. Bad value: less than 0 [bughuntingInvalidArgValue] 638 | strncpy(&str[i], &str[i + 1], len - i); 639 | ^ 640 | __tests__/test.c:93:71: note: Calling timestamp 641 | printf("[%s] SERVER: Connection lost with client(%d)\n", timestamp(), 642 | ^ 643 | __tests__/test.c:34:41: note: There is function call, cannot determine that 3rd argument value is valid. Bad value: less than 0 644 | strncpy(&str[i], &str[i + 1], len - i); 645 | ^ 646 | __tests__/test.c:34:14: error: Buffer read/write, when calling 'strncpy' it cannot be determined that 1st argument is not overflowed [bughuntingBufferOverflow] 647 | strncpy(&str[i], &str[i + 1], len - i); 648 | ^ 649 | __tests__/test.c:93:71: note: Calling timestamp 650 | printf("[%s] SERVER: Connection lost with client(%d)\n", timestamp(), 651 | ^ 652 | __tests__/test.c:34:14: note: Buffer read/write, when calling 'strncpy' it cannot be determined that 1st argument is not overflowed 653 | strncpy(&str[i], &str[i + 1], len - i); 654 | ^ 655 | __tests__/test.c:101:9: error: Cannot determine that 'buff[0]' is initialized [bughuntingUninit] 656 | bzero(buff, max_mssg_len); 657 | ^ 658 | __tests__/test.c:26:17: error: There is function call, cannot determine that 1st argument is initialized. [bughuntingUninitArg] 659 | str = asctime(local); 660 | ^ 661 | __tests__/test.c:107:73: note: Calling timestamp 662 | printf("[%s] SERVER: Connection lost with client(%d)\n", timestamp(), 663 | ^ 664 | __tests__/test.c:26:17: note: There is function call, cannot determine that 1st argument is initialized. 665 | str = asctime(local); 666 | ^ 667 | __tests__/test.c:29:20: error: There is function call, cannot determine that 1st argument is initialized. [bughuntingUninitArg] 668 | int len = strlen(str) + 1; 669 | ^ 670 | __tests__/test.c:107:73: note: Calling timestamp 671 | printf("[%s] SERVER: Connection lost with client(%d)\n", timestamp(), 672 | ^ 673 | __tests__/test.c:29:20: note: There is function call, cannot determine that 1st argument is initialized. 674 | int len = strlen(str) + 1; 675 | ^ 676 | __tests__/test.c:34:41: error: There is function call, cannot determine that 3rd argument value is valid. Bad value: less than 0 [bughuntingInvalidArgValue] 677 | strncpy(&str[i], &str[i + 1], len - i); 678 | ^ 679 | __tests__/test.c:107:73: note: Calling timestamp 680 | printf("[%s] SERVER: Connection lost with client(%d)\n", timestamp(), 681 | ^ 682 | __tests__/test.c:34:41: note: There is function call, cannot determine that 3rd argument value is valid. Bad value: less than 0 683 | strncpy(&str[i], &str[i + 1], len - i); 684 | ^ 685 | __tests__/test.c:34:14: error: Buffer read/write, when calling 'strncpy' it cannot be determined that 1st argument is not overflowed [bughuntingBufferOverflow] 686 | strncpy(&str[i], &str[i + 1], len - i); 687 | ^ 688 | __tests__/test.c:107:73: note: Calling timestamp 689 | printf("[%s] SERVER: Connection lost with client(%d)\n", timestamp(), 690 | ^ 691 | __tests__/test.c:34:14: note: Buffer read/write, when calling 'strncpy' it cannot be determined that 1st argument is not overflowed 692 | strncpy(&str[i], &str[i + 1], len - i); 693 | ^ 694 | __tests__/test.c:26:17: error: There is function call, cannot determine that 1st argument is initialized. [bughuntingUninitArg] 695 | str = asctime(local); 696 | ^ 697 | __tests__/test.c:117:58: note: Calling timestamp 698 | printf("[%s] DISCONNECTED: CLIENT(%d)\n", timestamp(), client_fd - 3); 699 | ^ 700 | __tests__/test.c:26:17: note: There is function call, cannot determine that 1st argument is initialized. 701 | str = asctime(local); 702 | ^ 703 | __tests__/test.c:29:20: error: There is function call, cannot determine that 1st argument is initialized. [bughuntingUninitArg] 704 | int len = strlen(str) + 1; 705 | ^ 706 | __tests__/test.c:117:58: note: Calling timestamp 707 | printf("[%s] DISCONNECTED: CLIENT(%d)\n", timestamp(), client_fd - 3); 708 | ^ 709 | __tests__/test.c:29:20: note: There is function call, cannot determine that 1st argument is initialized. 710 | int len = strlen(str) + 1; 711 | ^ 712 | __tests__/test.c:34:41: error: There is function call, cannot determine that 3rd argument value is valid. Bad value: less than 0 [bughuntingInvalidArgValue] 713 | strncpy(&str[i], &str[i + 1], len - i); 714 | ^ 715 | __tests__/test.c:117:58: note: Calling timestamp 716 | printf("[%s] DISCONNECTED: CLIENT(%d)\n", timestamp(), client_fd - 3); 717 | ^ 718 | __tests__/test.c:34:41: note: There is function call, cannot determine that 3rd argument value is valid. Bad value: less than 0 719 | strncpy(&str[i], &str[i + 1], len - i); 720 | ^ 721 | __tests__/test.c:34:14: error: Buffer read/write, when calling 'strncpy' it cannot be determined that 1st argument is not overflowed [bughuntingBufferOverflow] 722 | strncpy(&str[i], &str[i + 1], len - i); 723 | ^ 724 | __tests__/test.c:117:58: note: Calling timestamp 725 | printf("[%s] DISCONNECTED: CLIENT(%d)\n", timestamp(), client_fd - 3); 726 | ^ 727 | __tests__/test.c:34:14: note: Buffer read/write, when calling 'strncpy' it cannot be determined that 1st argument is not overflowed 728 | strncpy(&str[i], &str[i + 1], len - i); 729 | ^ 730 | __tests__/test.c:26:17: error: There is function call, cannot determine that 1st argument is initialized. [bughuntingUninitArg] 731 | str = asctime(local); 732 | ^ 733 | __tests__/test.c:118:65: note: Calling timestamp 734 | printf("[%s] SERVER: Exiting from Thread %ld\n", timestamp(), 735 | ^ 736 | __tests__/test.c:26:17: note: There is function call, cannot determine that 1st argument is initialized. 737 | str = asctime(local); 738 | ^ 739 | __tests__/test.c:29:20: error: There is function call, cannot determine that 1st argument is initialized. [bughuntingUninitArg] 740 | int len = strlen(str) + 1; 741 | ^ 742 | __tests__/test.c:118:65: note: Calling timestamp 743 | printf("[%s] SERVER: Exiting from Thread %ld\n", timestamp(), 744 | ^ 745 | __tests__/test.c:29:20: note: There is function call, cannot determine that 1st argument is initialized. 746 | int len = strlen(str) + 1; 747 | ^ 748 | __tests__/test.c:34:41: error: There is function call, cannot determine that 3rd argument value is valid. Bad value: less than 0 [bughuntingInvalidArgValue] 749 | strncpy(&str[i], &str[i + 1], len - i); 750 | ^ 751 | __tests__/test.c:118:65: note: Calling timestamp 752 | printf("[%s] SERVER: Exiting from Thread %ld\n", timestamp(), 753 | ^ 754 | __tests__/test.c:34:41: note: There is function call, cannot determine that 3rd argument value is valid. Bad value: less than 0 755 | strncpy(&str[i], &str[i + 1], len - i); 756 | ^ 757 | __tests__/test.c:34:14: error: Buffer read/write, when calling 'strncpy' it cannot be determined that 1st argument is not overflowed [bughuntingBufferOverflow] 758 | strncpy(&str[i], &str[i + 1], len - i); 759 | ^ 760 | __tests__/test.c:118:65: note: Calling timestamp 761 | printf("[%s] SERVER: Exiting from Thread %ld\n", timestamp(), 762 | ^ 763 | __tests__/test.c:34:14: note: Buffer read/write, when calling 'strncpy' it cannot be determined that 1st argument is not overflowed 764 | strncpy(&str[i], &str[i + 1], len - i); 765 | ^ 766 | __tests__/test.c:26:17: error: There is function call, cannot determine that 1st argument is initialized. [bughuntingUninitArg] 767 | str = asctime(local); 768 | ^ 769 | __tests__/test.c:124:49: note: Calling timestamp 770 | printf("[%s] CLIENT_%d@host:~$%s", timestamp(), client_fd - 3, buff); 771 | ^ 772 | __tests__/test.c:26:17: note: There is function call, cannot determine that 1st argument is initialized. 773 | str = asctime(local); 774 | ^ 775 | __tests__/test.c:29:20: error: There is function call, cannot determine that 1st argument is initialized. [bughuntingUninitArg] 776 | int len = strlen(str) + 1; 777 | ^ 778 | __tests__/test.c:124:49: note: Calling timestamp 779 | printf("[%s] CLIENT_%d@host:~$%s", timestamp(), client_fd - 3, buff); 780 | ^ 781 | __tests__/test.c:29:20: note: There is function call, cannot determine that 1st argument is initialized. 782 | int len = strlen(str) + 1; 783 | ^ 784 | __tests__/test.c:34:41: error: There is function call, cannot determine that 3rd argument value is valid. Bad value: less than 0 [bughuntingInvalidArgValue] 785 | strncpy(&str[i], &str[i + 1], len - i); 786 | ^ 787 | __tests__/test.c:124:49: note: Calling timestamp 788 | printf("[%s] CLIENT_%d@host:~$%s", timestamp(), client_fd - 3, buff); 789 | ^ 790 | __tests__/test.c:34:41: note: There is function call, cannot determine that 3rd argument value is valid. Bad value: less than 0 791 | strncpy(&str[i], &str[i + 1], len - i); 792 | ^ 793 | __tests__/test.c:34:14: error: Buffer read/write, when calling 'strncpy' it cannot be determined that 1st argument is not overflowed [bughuntingBufferOverflow] 794 | strncpy(&str[i], &str[i + 1], len - i); 795 | ^ 796 | __tests__/test.c:124:49: note: Calling timestamp 797 | printf("[%s] CLIENT_%d@host:~$%s", timestamp(), client_fd - 3, buff); 798 | ^ 799 | __tests__/test.c:34:14: note: Buffer read/write, when calling 'strncpy' it cannot be determined that 1st argument is not overflowed 800 | strncpy(&str[i], &str[i + 1], len - i); 801 | ^ 802 | __tests__/test.c:267:9: error: Buffer read/write, when calling 'memset' it cannot be determined that 1st argument is not overflowed [bughuntingBufferOverflow] 803 | memset(&thread_args, 0, sizeof(thread_args)); 804 | ^ 805 | __tests__/test.c:26:17: error: There is function call, cannot determine that 1st argument is initialized. [bughuntingUninitArg] 806 | str = asctime(local); 807 | ^ 808 | __tests__/test.c:332:74: note: Calling timestamp 809 | printf("[%s] SERVER: ERROR in creating the Thread %ld\n", timestamp(), 810 | ^ 811 | __tests__/test.c:26:17: note: There is function call, cannot determine that 1st argument is initialized. 812 | str = asctime(local); 813 | ^ 814 | __tests__/test.c:29:20: error: There is function call, cannot determine that 1st argument is initialized. [bughuntingUninitArg] 815 | int len = strlen(str) + 1; 816 | ^ 817 | __tests__/test.c:332:74: note: Calling timestamp 818 | printf("[%s] SERVER: ERROR in creating the Thread %ld\n", timestamp(), 819 | ^ 820 | __tests__/test.c:29:20: note: There is function call, cannot determine that 1st argument is initialized. 821 | int len = strlen(str) + 1; 822 | ^ 823 | __tests__/test.c:34:41: error: There is function call, cannot determine that 3rd argument value is valid. Bad value: less than 0 [bughuntingInvalidArgValue] 824 | strncpy(&str[i], &str[i + 1], len - i); 825 | ^ 826 | __tests__/test.c:332:74: note: Calling timestamp 827 | printf("[%s] SERVER: ERROR in creating the Thread %ld\n", timestamp(), 828 | ^ 829 | __tests__/test.c:34:41: note: There is function call, cannot determine that 3rd argument value is valid. Bad value: less than 0 830 | strncpy(&str[i], &str[i + 1], len - i); 831 | ^ 832 | __tests__/test.c:34:14: error: Buffer read/write, when calling 'strncpy' it cannot be determined that 1st argument is not overflowed [bughuntingBufferOverflow] 833 | strncpy(&str[i], &str[i + 1], len - i); 834 | ^ 835 | __tests__/test.c:332:74: note: Calling timestamp 836 | printf("[%s] SERVER: ERROR in creating the Thread %ld\n", timestamp(), 837 | ^ 838 | __tests__/test.c:34:14: note: Buffer read/write, when calling 'strncpy' it cannot be determined that 1st argument is not overflowed 839 | strncpy(&str[i], &str[i + 1], len - i); 840 | ^ 841 | __tests__/test.c:26:17: error: There is function call, cannot determine that 1st argument is initialized. [bughuntingUninitArg] 842 | str = asctime(local); 843 | ^ 844 | __tests__/test.c:340:21: note: Calling timestamp 845 | timestamp(), t_id, client_fd - 3); 846 | ^ 847 | __tests__/test.c:26:17: note: There is function call, cannot determine that 1st argument is initialized. 848 | str = asctime(local); 849 | ^ 850 | __tests__/test.c:29:20: error: There is function call, cannot determine that 1st argument is initialized. [bughuntingUninitArg] 851 | int len = strlen(str) + 1; 852 | ^ 853 | __tests__/test.c:340:21: note: Calling timestamp 854 | timestamp(), t_id, client_fd - 3); 855 | ^ 856 | __tests__/test.c:29:20: note: There is function call, cannot determine that 1st argument is initialized. 857 | int len = strlen(str) + 1; 858 | ^ 859 | __tests__/test.c:34:41: error: There is function call, cannot determine that 3rd argument value is valid. Bad value: less than 0 [bughuntingInvalidArgValue] 860 | strncpy(&str[i], &str[i + 1], len - i); 861 | ^ 862 | __tests__/test.c:340:21: note: Calling timestamp 863 | timestamp(), t_id, client_fd - 3); 864 | ^ 865 | __tests__/test.c:34:41: note: There is function call, cannot determine that 3rd argument value is valid. Bad value: less than 0 866 | strncpy(&str[i], &str[i + 1], len - i); 867 | ^ 868 | __tests__/test.c:34:14: error: Buffer read/write, when calling 'strncpy' it cannot be determined that 1st argument is not overflowed [bughuntingBufferOverflow] 869 | strncpy(&str[i], &str[i + 1], len - i); 870 | ^ 871 | __tests__/test.c:340:21: note: Calling timestamp 872 | timestamp(), t_id, client_fd - 3); 873 | ^ 874 | __tests__/test.c:34:14: note: Buffer read/write, when calling 'strncpy' it cannot be determined that 1st argument is not overflowed 875 | strncpy(&str[i], &str[i + 1], len - i); 876 | ^ 877 | __tests__/test.c:342:18: error: Array index out of bounds, cannot determine that ++thread_count is less than 20 [bughuntingArrayIndexOutOfBounds] 878 | threads_pool[++thread_count] = t_id; 879 | ^ 880 | __tests__/test.c:342:18: error: Array index out of bounds, cannot determine that ++thread_count is not negative [bughuntingArrayIndexNegative] 881 | threads_pool[++thread_count] = t_id; 882 | ^ 883 | nofile:0:0: information: Cppcheck cannot find all the include files. Cppcheck can check the code without the include files found. But the results will probably be more accurate if all the include files are found. Please check your project's include directories and add all of them as include directories for Cppcheck. To see what files Cppcheck cannot find use --check-config. [missingInclude] 884 | 885 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | FROM facthunder/cppcheck 2 | ADD ./src/entrypoint.py /entrypoint.py 3 | ENTRYPOINT ["python", "/entrypoint.py"] 4 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2021 Dipankar Pal 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 | ![cppcheck-action](https://socialify.git.ci/deep5050/cppcheck-action/image?description=1&logo=https%3A%2F%2Fi.imgur.com%2FbDs8nfo.png&theme=Light) 3 | 4 | 5 |
6 |

7 |

YouTube Channel Views 8 | YouTube Channel Subscribers

9 | release 10 |

11 | 12 |
13 | 14 | 15 | ## [subscribe to service updates](https://github.com/deep5050/cppcheck-action/issues/11) 16 | 17 | > ** Please participate on this 18 | > [poll](https://github.com/deep5050/cppcheck-action/issues/10) for a feature 19 | > planned by me ** 20 | 21 | 22 | ## What is cppcheck? 23 | 24 | [cppcheck](https://github.com/danmar/cppcheck) is a static analysis tool for 25 | C/C++ code. It provides unique code analysis to detect bugs and focuses on 26 | detecting undefined behavior and dangerous coding constructs. The goal is to 27 | have very few false positives. Cppcheck is designed to be able to analyze your 28 | C/C++ code even if it has non-standard syntax (common in embedded projects). 29 | 30 | ## How to use? 31 | 32 | Create `cppcheck.yml` under `.github/workflows` With the following contents 33 | 34 | ### Default configuration 35 | 36 | ```yml 37 | name: cppcheck-action-test 38 | on: [push] 39 | 40 | jobs: 41 | build: 42 | name: cppcheck-test 43 | runs-on: ubuntu-latest 44 | steps: 45 | - uses: actions/checkout@v2 46 | 47 | - name: cppcheck 48 | uses: deep5050/cppcheck-action@main 49 | with: 50 | github_token: ${{ secrets.GITHUB_TOKEN}} 51 | 52 | 53 | - name: publish report 54 | uses: mikeal/publish-to-github-action@master 55 | env: 56 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 57 | BRANCH_NAME: 'main' # your branch name goes here 58 | ``` 59 | 60 | ### Advanced configuration 61 | 62 | ```yml 63 | name: cppcheck-action 64 | on: [push] 65 | 66 | jobs: 67 | build: 68 | name: cppcheck 69 | runs-on: ubuntu-latest 70 | steps: 71 | - uses: actions/checkout@v2 72 | - name: cppcheck 73 | uses: deep5050/cppcheck-action@main 74 | with: 75 | github_token: ${{ secrets.GITHUB_TOKEN}} 76 | check_library: 77 | skip_preprocessor: 78 | enable: 79 | exclude_check: 80 | inconclusive: 81 | inline_suppression: 82 | force_language: 83 | force: 84 | max_ctu_depth: 85 | platform: 86 | std: 87 | output_file: 88 | other_options: 89 | 90 | - name: publish report 91 | uses: mikeal/publish-to-github-action@master 92 | env: 93 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 94 | BRANCH_NAME: 'main' # your branch name goes here 95 | ``` 96 | 97 | ### Input options 98 | 99 | | Option | Value | Description | Default | 100 | | :--- | :--- | :--- | :--- | 101 | | **check_library** | `enable`, `disable` | Show information messages when library files have incomplete info | `disable` | 102 | | **skip_preprocessor** | `enable`, `disable` | Print preprocessor output on stdout and don't do any further processing | `disable` | 103 | | **enable** | `all`, `warning`, `style`, `performance`, `portability`, `information`, `unusedFunction`, `missingInclude` | Enable additional checks. if you want to enable multiple checking at once, separate them using `,` without any blank space. example: `style,warning,performance` | `all` | 104 | | **exclude_check** | `./path/to/ignore` | Give a file or directory path to exclude from checking. example: `./no_check.cpp` | nothing to ignore | 105 | | **inconclusive** | `enable`, `disable` | Allow that Cppcheck reports even though the analysis is inconclusive | `enable` | 106 | | **inline_suppression** | `enable`, `disable` | Enable inline suppressions. Use them by placing one or more comments, like: '// cppcheck-suppress warningId' | `disable` | 107 | | **force_language** | `c`, `c++` | Forces cppcheck to check all files as the given language. Valid values are: `c`, `c++` | auto-detected | 108 | | **force** | `enable`, `disable` | Force checking of all configurations in files | `disable` | 109 | | **max_ctu_depth** | `number` | Max depth in whole program analysis. A larger value will mean more errors can be found but also means the analysis will be slower. example: `4` | `2` | 110 | | **platform** | `unix32`, `unix64`, `win32A`, `win32W`, `win64`, `avr8`, `elbrus-e1cp`, `pic8`, `pic8-enhanced`, `pic16`, `mips32`, `native`, `unspecified`, | Specifies platform specific types and sizes | `unspecified` | 111 | | **std** | `c89`, `c99`, `c11`, `c++11`, `c++14`, `c++17`, `c++20` | Set the C/C++ standard | `c11`, `c++20` | 112 | | **output_file** | `./path/to/output/file.txt` | Give a filename for the output report | `./cppcheck_report.txt` | 113 | | **other_options** | `--option1 --option2=value -opt3` | Any other options you want to add, separate with a space, wrong options will cause a failure. example: `--bug-hunting --verbose`| `disable` | 114 | 115 | 116 | For further details check 117 | [cppcheck documentations](http://cppcheck.sourceforge.net/manual.pdf) 118 | 119 | ## License 120 | 121 | > MIT License 122 | 123 | > Copyright (c) 2021 Dipankar Pal 124 | 125 | Permission is hereby granted, free of charge, to any person obtaining a copy of 126 | this software and associated documentation files (the "Software"), to deal in 127 | the Software without restriction, including without limitation the rights to 128 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 129 | the Software, and to permit persons to whom the Software is furnished to do so, 130 | subject to the following conditions: 131 | 132 | The above copyright notice and this permission notice shall be included in all 133 | copies or substantial portions of the Software. 134 | 135 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 136 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 137 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 138 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 139 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 140 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 141 | 142 | ## Thanks 143 | 144 | Icons made by 145 | Freepik 146 | from www.flaticon.com 147 | 148 | ## Contributors ✨ 149 | 150 | Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/docs/en/emoji-key)): 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 |

Bader

⚠️

Stefan Hagen

🚇 ⚠️ 💻
161 | 162 | 163 | 164 | 165 | 166 | This project follows the [all-contributors](https://github.com/all-contributors/all-contributors) specification. Contributions of any kind welcome! 167 | 168 | ### Related 169 | [![deep5050/count-comments-action - GitHub](https://gh-card.dev/repos/deep5050/count-comments-action.svg)](https://github.com/deep5050/count-comments-action) 170 | 171 | [![deep5050/MastJokeMara - GitHub](https://gh-card.dev/repos/deep5050/MastJokeMara.svg)](https://github.com/deep5050/MastJokeMara) 172 | 173 | [![deep5050/memes-on-issues-action - GitHub](https://gh-card.dev/repos/deep5050/memes-on-issues-action.svg)](https://github.com/deep5050/memes-on-issues-action) 174 | 175 | [![deep5050/smart-radio - GitHub](https://gh-card.dev/repos/deep5050/smart-radio.svg)](https://github.com/deep5050/smart-radio) 176 | -------------------------------------------------------------------------------- /__tests__/client/client.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | 19 | #include "../tools/connection.h" 20 | #include "../tools/log.h" 21 | 22 | static pthread_t t_id; 23 | static int client_fd; 24 | 25 | /* ********************************************************* */ 26 | void stop_child_thread() 27 | { 28 | int ret = pthread_join(t_id, NULL); /* Stop the message receveing handler thread */ 29 | if (!ret) 30 | { 31 | LOG(_LOG_INFO_, "Receive message handler thread stopped"); 32 | } 33 | else 34 | { 35 | LOG(_LOG_ERR_, "Could not stop receive message handler thread"); 36 | } 37 | } 38 | /* ******************************************* */ 39 | 40 | /* stop the service on SIGINT command */ 41 | void sigint_handler(int sig) 42 | { 43 | send(client_fd, "/quit", 5, 0); /* Server needs to stop its service for the client too */ 44 | stop_child_thread(); /* Stop the message receveing handler thread */ 45 | 46 | close(client_fd); 47 | exit(EXIT_SUCCESS); 48 | } 49 | 50 | /* ****************************************************** */ 51 | 52 | /* Thread to handle receive messages from other clients asynchronously */ 53 | void *rcv_msg_handler(void *arguments) 54 | { 55 | char name[MAX_USERNAME_LEN], rcvd_msg[MAX_MSG_LEN]; 56 | int rcvd_bytes; 57 | 58 | memset(name, '\0', MAX_USERNAME_LEN); 59 | 60 | struct args *p_args = (struct args *)arguments; 61 | strncpy(name, p_args->name, strlen(p_args->name) + 1); 62 | 63 | while (1) 64 | { 65 | memset(rcvd_msg, '\0', MAX_MSG_LEN); 66 | 67 | rcvd_bytes = recv(client_fd, &rcvd_msg, sizeof(rcvd_msg), 0); 68 | if (rcvd_bytes > 0) 69 | { 70 | strip_newline(rcvd_msg); 71 | if (strlen(rcvd_msg)) 72 | { 73 | printf("\n\x1b[35m%s@server:~$\x1b[0m%s", name, rcvd_msg); 74 | fflush(stdout); 75 | } 76 | } 77 | } 78 | } 79 | 80 | /* ***************************************************************************************** */ 81 | 82 | int main(int argc, char *argv[]) 83 | { 84 | char server_ip[INET_ADDRSTRLEN], server_port[5], name[MAX_USERNAME_LEN], greetings_from_server[100], buff[MAX_MSG_LEN]; 85 | 86 | int opt, port, debug_level, connect_status, sent_bytes, recv_bytes, temp_return_value, n; 87 | 88 | bool server_ip_flag = false, server_port_flag = false, 89 | debug_level_flag = false, name_flag = false; 90 | 91 | char *strptr; 92 | 93 | struct sockaddr_in server_addr; 94 | struct args thread_args; 95 | 96 | memset(&server_addr, 0, sizeof(server_addr)); 97 | memset(server_ip, '\0', sizeof(server_ip)); 98 | memset(server_port, '\0', sizeof(server_port)); 99 | memset(name, '\0', sizeof(name)); 100 | memset(buff, '\0', sizeof(buff)); 101 | 102 | while ((opt = getopt(argc, argv, "-a:p:D:n:")) != -1) 103 | { 104 | switch (opt) 105 | { 106 | case 'p': 107 | server_port_flag = true; 108 | strncpy(server_port, optarg, 4); 109 | LOG(_LOG_INFO_, "provided port number: %s", server_port); 110 | break; 111 | case 'a': 112 | server_ip_flag = true; 113 | strncpy(server_ip, optarg, INET_ADDRSTRLEN); 114 | LOG(_LOG_INFO_, "provided IP: %s", server_ip); 115 | break; 116 | 117 | case 'n': 118 | name_flag = true; 119 | strncpy(name, optarg, strlen(optarg) + 1); 120 | LOG(_LOG_INFO_, "provided name for the client: %s", name); 121 | break; 122 | 123 | case 'D': 124 | debug_level_flag = true; 125 | char *buff1; 126 | char temp[5]; 127 | memset(temp, '\0', sizeof(temp)); 128 | strncpy(temp, optarg, 4); 129 | debug_level = strtol(temp, &buff1, 10); 130 | LOG(_LOG_INFO_, "provided debug level value: %d", debug_level); 131 | 132 | if (debug_level < 0) 133 | debug_level = 1; 134 | if (debug_level > 3) 135 | debug_level = 3; 136 | 137 | SET_LOG_LEVEL(debug_level); 138 | buff1 = NULL; 139 | break; 140 | case '?': 141 | break; 142 | case ':': 143 | LOG(_LOG_WARN_, "Missing arg for %c", optopt); 144 | exit(EXIT_FAILURE); 145 | case 1: 146 | LOG(_LOG_ERR_, " USAGE: "); 147 | break; 148 | } 149 | } 150 | 151 | /* If any arguments missing, print usage guide and quit */ 152 | if (!server_ip_flag || !server_port_flag || !debug_level_flag || !name_flag) 153 | { 154 | LOG(_LOG_ERR_, " USAGE: "); 155 | exit(EXIT_FAILURE); 156 | } 157 | 158 | /* Convert "localhost" to "0.0.0.0" */ 159 | if (strncmp(server_ip, "localhost", 9) == 0) 160 | { 161 | bzero(server_ip, sizeof(server_ip)); 162 | strcpy(server_ip, "0.0.0.0"); 163 | LOG(_LOG_INFO_, "connection request to a local server"); 164 | } 165 | 166 | port = strtol(server_port, &strptr, 10); 167 | 168 | server_addr.sin_family = AF_INET; 169 | 170 | /* assign the same port where the server is running */ 171 | server_addr.sin_port = htons(port); 172 | 173 | /* IP presentation format to network format */ 174 | temp_return_value = inet_pton(AF_INET, server_ip, &server_addr.sin_addr); 175 | 176 | if (temp_return_value <= 0) 177 | { 178 | if (temp_return_value == 0) 179 | LOG(_LOG_ERR_, "server IP is Not in presentation format"); 180 | exit(EXIT_FAILURE); 181 | } 182 | 183 | client_fd = socket(AF_INET, SOCK_STREAM, 0); 184 | 185 | /* Send a total of 2 SYN packets => Timeout ~7s */ 186 | int synRetries = 2; 187 | setsockopt(client_fd, IPPROTO_TCP, TCP_SYNCNT, &synRetries, sizeof(synRetries)); 188 | 189 | if (client_fd < 0) 190 | { 191 | LOG(_LOG_ERR_, "Error in creating socket"); 192 | exit(EXIT_FAILURE); 193 | } 194 | 195 | LOG(_LOG_INFO_, "Connection request sent, waiting for server to respond"); 196 | connect_status = connect(client_fd, (struct sockaddr *)&server_addr, sizeof(server_addr)); 197 | 198 | if (connect_status < 0) 199 | { 200 | LOG(_LOG_ERR_, "could not connect to the server"); 201 | exit(EXIT_FAILURE); 202 | } 203 | 204 | /* send client's name to the server */ 205 | sent_bytes = send(client_fd, &name, strlen(name), 0); 206 | if (sent_bytes == -1) 207 | { 208 | LOG(_LOG_ERR_, "could not sent the name"); 209 | close(client_fd); 210 | exit(EXIT_FAILURE); 211 | } 212 | 213 | /* Waiting for the server to greet with the name it recently sent */ 214 | recv_bytes = recv(client_fd, &greetings_from_server, sizeof(greetings_from_server), 0); 215 | if (recv_bytes < 0) 216 | { 217 | LOG(_LOG_ERR_, "could not established the connection properly"); 218 | close(client_fd); 219 | exit(EXIT_FAILURE); 220 | } 221 | else 222 | { 223 | LOG(_LOG_INFO_, "%s", greetings_from_server); 224 | } 225 | 226 | /* Protocol defined handshaking is done, 227 | provide a virtual terminal for the actual conversation */ 228 | LOG(_LOG_INFO_, "Remote Terminal is Ready"); 229 | LOG(_LOG_INFO_, "Type your message (Type '!q' or hit ^C to quit):"); 230 | 231 | /* Prepare the arguments for the rcv_msg_handler thread */ 232 | thread_args.client_fd = client_fd; 233 | strncpy(thread_args.name, name, strlen(name)); 234 | 235 | if (pthread_create(&t_id, NULL, rcv_msg_handler, (void *)&thread_args) != 0) 236 | { 237 | LOG(_LOG_ERR_, "couldn't create the Thread %ld\n", t_id); 238 | exit(EXIT_FAILURE); 239 | } 240 | 241 | LOG(_LOG_INFO_, "New thread created to receive messages"); 242 | 243 | while (1) 244 | { 245 | n = 0; 246 | bzero(buff, MAX_MSG_LEN); 247 | signal(SIGINT, sigint_handler); 248 | printf("\x1b[35m%s@SERVER:~$\x1b[0m", name); /* virtual terminal */ 249 | fflush(stdout); 250 | 251 | while ((buff[n++] = getchar()) != '\n') 252 | ; 253 | 254 | strip_newline(buff); 255 | if (!strlen(buff) || !strncmp(buff, " ", 1) || !strncmp(buff, "\n", 1)) 256 | { 257 | /* it's a blank message, don't send it */ 258 | continue; 259 | } 260 | 261 | /* only if it is a /help command, skip sending it to the server */ 262 | if (!strncmp(buff, "/help", 5)) 263 | { 264 | printf("\x1b[35m%s@SERVER:~$%s\x1b[0m", name, "1./connect : to connect to a user 2./quit: to exit 3./help: to show this help message\n"); 265 | continue; 266 | } 267 | sent_bytes = send(client_fd, &buff, sizeof(buff), 0); /* Send the message to the server */ 268 | if (sent_bytes == -1) 269 | { 270 | LOG(_LOG_WARN_, "could not sent the last message try again"); 271 | } 272 | 273 | /* even /quit command needs to be sent to server to inform server 274 | that the client is about to quit */ 275 | 276 | /* Now check if the last message was a quit command 277 | if it was, quit the client and */ 278 | if (strncmp(buff, "/quit", 5) == 0) 279 | { 280 | // FIXME stop child too 281 | close(client_fd); 282 | LOG(_LOG_INFO_, "Terminated"); 283 | exit(EXIT_SUCCESS); 284 | /* Close the child thread too */ 285 | stop_child_thread(); 286 | } 287 | } 288 | 289 | return 0; 290 | } -------------------------------------------------------------------------------- /__tests__/exclude/perfect_square.c: -------------------------------------------------------------------------------- 1 | #include 2 | int main() 3 | { 4 | printf("\n\n\t\tStudytonight - Best place to learn\n\n\n"); 5 | 6 | // variable declaration 7 | int i, number; 8 | 9 | // take user input 10 | printf("Enter a number: "); 11 | scanf("%d", &number); 12 | 13 | // loop to check number is perfect square or not 14 | for(i = 0; i <= number; i++) 15 | { 16 | if(number == i*i) 17 | { 18 | printf("\n\n\n\t\t\t%d is a perfect square\n\n\n", number); 19 | 20 | printf("\n\n\t\t\tCoding is Fun !\n\n\n"); 21 | return 0; // same as using break in this case to end the program 22 | } 23 | } 24 | printf("\n\n\n\t\t\t%d is not a perfect square\n", number); 25 | printf("\n\n\t\t\tCoding is Fun !\n\n\n"); 26 | return 0; 27 | } 28 | -------------------------------------------------------------------------------- /__tests__/fibonacci.c: -------------------------------------------------------------------------------- 1 | #include 2 | // declaring the function 3 | void printFibo(int ); 4 | 5 | int main() 6 | { 7 | printf("\n\n\t\tStudytonight - Best place to learn\n\n\n"); 8 | int k, n; 9 | long int i = 0, j = 1; 10 | printf("Enter the length of the Fibonacci series: "); 11 | scanf("%d", &n); 12 | printf("\n\nfirst %d terms of Fibonacci series are:\n\n\n",n); 13 | printf("%d ", 1); 14 | printFibo(n); 15 | printf("\n\n\t\t\tCoding is Fun !\n\n\n"); 16 | return 0; 17 | } 18 | 19 | void printFibo(int aj) 20 | { 21 | static long int first = 0, second = 1, sum; 22 | if(aj > 1) 23 | { 24 | sum = first + second; 25 | first = second; 26 | second = sum; 27 | printf("%ld ", sum); 28 | printFibo(aj-1); // recursive call 29 | } 30 | else 31 | { 32 | // after the elements, for line break 33 | printf("\n\n\n"); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /__tests__/server/server.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | 19 | #include "../tools/log.h" 20 | #include "../tools/connection.h" 21 | 22 | #define MAX_THREAD_COUNT 20 23 | 24 | static int thread_count = -1; 25 | static pthread_t threads_pool[MAX_THREAD_COUNT]; 26 | 27 | void kill_all_threads() 28 | { 29 | int killed_threads = 0; 30 | for (int i = 0; i <= thread_count; i++) 31 | { 32 | int return_val = pthread_cancel(threads_pool[i]); 33 | if (return_val != ESRCH) 34 | killed_threads++; 35 | } 36 | if (killed_threads) 37 | LOG(_LOG_WARN_, "%d threads did not shutdown properly", killed_threads); 38 | else 39 | LOG(_LOG_INFO_, "All threads exited successfully"); 40 | } 41 | 42 | void INTR_handler(int sig) 43 | { 44 | //TODO clear the database 45 | kill_all_threads(); 46 | close(server_fd); 47 | LOG(_LOG_INFO_, "SERVER CLOSED"); 48 | exit(0); 49 | } 50 | 51 | /* *************************************************** */ 52 | 53 | int main(int argc, char *argv[]) 54 | { 55 | 56 | int opt, backlog, debug_level; 57 | bool port_flag = false, backlog_flag = false, debug_level_flag = false; 58 | 59 | char port[5]; 60 | memset(port, '\0', sizeof(port)); 61 | 62 | while ((opt = getopt(argc, argv, "-p:b:D:")) != -1) 63 | { 64 | switch (opt) 65 | { 66 | case 'p': 67 | port_flag = true; 68 | strncpy(port, optarg, 4); 69 | LOG(_LOG_INFO_, "provided port number: %s", port); 70 | break; 71 | case 'b': 72 | backlog_flag = true; 73 | char *buff; 74 | char temp[5]; 75 | memset(temp, '\0', sizeof(temp)); 76 | strncpy(temp, optarg, 4); 77 | backlog = strtol(temp, &buff, 10); 78 | LOG(_LOG_INFO_, "provided backlog value: %d", backlog); 79 | buff = NULL; 80 | break; 81 | case 'D': 82 | debug_level_flag = true; 83 | char *buff1; 84 | memset(temp, '\0', sizeof(temp)); 85 | strncpy(temp, optarg, 4); 86 | debug_level = strtol(temp, &buff1, 10); 87 | LOG(_LOG_INFO_, "provided debug level value: %d", debug_level); 88 | 89 | if (debug_level < 0) 90 | debug_level = 1; 91 | if (debug_level > 3) 92 | debug_level = 3; 93 | 94 | SET_LOG_LEVEL(debug_level); 95 | buff1 = NULL; 96 | break; 97 | case '?': 98 | break; 99 | case ':': 100 | LOG(_LOG_WARN_, "Missing arg for %c", optopt); 101 | exit(EXIT_FAILURE); 102 | case 1: 103 | LOG(_LOG_ERR_, " USAGE: "); 104 | break; 105 | } 106 | } 107 | 108 | if (!backlog_flag || !port_flag || !debug_level_flag) 109 | { 110 | LOG(_LOG_ERR_, "port, backlog and debug level values are mandatory"); 111 | exit(EXIT_FAILURE); 112 | } 113 | 114 | /* Initializing all the variables only it passes the getopt() checking */ 115 | int client_fd, server_status, bind_status, listen_status, accept_status, 116 | addr_status, n = 0, yes = 1, bytes_sent; 117 | 118 | /* Initializing all the queues */ 119 | STAILQ_INIT(&head); 120 | STAILQ_INIT(&message_head); 121 | 122 | pthread_t t_id; /* Child thread ID */ 123 | struct addrinfo server_addr, *results, *p; 124 | struct sockaddr_in client_addr; 125 | struct args thread_args; /* Child treads argument holder */ 126 | memset(&thread_args, 0, sizeof(thread_args)); 127 | 128 | socklen_t client_addr_size = sizeof(client_addr); 129 | 130 | char buff[MAX_MSG_LEN], addr[INET_ADDRSTRLEN]; 131 | 132 | memset(&server_addr, 0, sizeof(server_addr)); 133 | memset(&client_addr, 0, sizeof(client_addr)); 134 | 135 | server_addr.ai_family = PF_INET; /* IPv4 */ 136 | server_addr.ai_socktype = SOCK_STREAM; /* tcp Stream */ 137 | server_addr.ai_flags = AI_PASSIVE; /* fill ip automatically */ 138 | 139 | /* get all the available address of this machine */ 140 | 141 | if ((addr_status = getaddrinfo(NULL, port, &server_addr, &results)) != 0) 142 | { 143 | LOG(_LOG_ERR_, "getaddrinfo(): %s", gai_strerror(addr_status)); 144 | exit(EXIT_FAILURE); 145 | } 146 | 147 | /* bind a socket at the first available address */ 148 | for (p = results; p != NULL; p = p->ai_next) 149 | { 150 | 151 | inet_ntop(p->ai_family, p->ai_addr, addr, sizeof(addr)); 152 | LOG(_LOG_INFO_, "Trying to build on %s", addr); 153 | 154 | if ((server_fd = socket(p->ai_family, p->ai_socktype, p->ai_protocol)) == -1) 155 | { 156 | continue; /* if socket can not be created on this address try another */ 157 | } 158 | if (setsockopt(server_fd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(int)) == -1) 159 | { 160 | LOG(_LOG_ERR_, "Error ocurred under setsockopt()"); 161 | exit(EXIT_FAILURE); 162 | } 163 | 164 | if (((bind_status = bind(server_fd, p->ai_addr, p->ai_addrlen)) == -1)) 165 | { 166 | // LOG(_LOG_ERR_,"error ocurred under bind()"); 167 | continue; 168 | } 169 | 170 | /** 171 | * control reaches here if all the above conditions satifie 172 | * we have successfully bound a socket and can exit from this loop 173 | */ 174 | inet_ntop(p->ai_family, p->ai_addr, addr, sizeof(addr)); 175 | break; 176 | } 177 | 178 | freeaddrinfo(results); 179 | 180 | /** 181 | * if we get p== NULL that means we couldn't bind to any of the addresses 182 | * should return from the program 183 | */ 184 | 185 | if (p == NULL) 186 | { 187 | LOG(_LOG_ERR_, "Couldn't build a server"); 188 | exit(EXIT_FAILURE); 189 | } 190 | 191 | listen_status = listen(server_fd, backlog); 192 | if (listen_status == -1) 193 | { 194 | LOG(_LOG_ERR_, "Error ocurred under listen()"); 195 | exit(EXIT_FAILURE); 196 | } 197 | 198 | /* If control reaches here, everything is Ok */ 199 | LOG(_LOG_INFO_, "UP and LISTENING on %s:%s with BACKLOG %d", addr, port, backlog); 200 | 201 | char greetings[] = "SERVER: Hi client,you are now connected"; 202 | char sorry[] = "SERVER: sorry could not give the service right now"; 203 | 204 | LOG(_LOG_INFO_, "SERVER is Waiting for connections"); 205 | 206 | while (1) 207 | { 208 | signal(SIGINT, INTR_handler); 209 | 210 | inet_ntop(client_addr.sin_family, &client_addr.sin_addr.s_addr, addr, sizeof(addr)); 211 | 212 | client_fd = accept(server_fd, (struct sockaddr *)&client_addr, &client_addr_size); 213 | if (client_fd < 0) 214 | { 215 | // perror("ERROR:"); 216 | LOG(_LOG_ERR_, "Could not connect to the client properly, fd: %d", client_fd); 217 | continue; 218 | } 219 | 220 | LOG(_LOG_INFO_, "NEW CLIENT: ID(%d): %s:%d", client_fd, addr, ntohs(client_addr.sin_port)); 221 | 222 | /* Filling the thread argument */ 223 | thread_args.client_fd = client_fd; 224 | thread_args.name[0] = '\0'; /* As we don't know the username of the client yet, 225 | will be filled up later by the child thread */ 226 | 227 | /* A thread is created to handle full duplex communication with a new client */ 228 | if (pthread_create(&t_id, NULL, service_clients, (void *)&thread_args) != 0) 229 | { 230 | LOG(_LOG_ERR_, "couldn't create the Thread %ld\n", t_id); 231 | send(client_fd, sorry, sizeof(sorry), 0); 232 | close(client_fd); 233 | continue; 234 | } 235 | 236 | LOG(_LOG_INFO_, "New thread created: %ld to service client ID %d", t_id, client_fd); 237 | pthread_detach(t_id); 238 | threads_pool[++thread_count] = t_id; 239 | } 240 | 241 | return 0; 242 | } 243 | -------------------------------------------------------------------------------- /__tests__/test.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #define max_mssg_len 1024 16 | 17 | int server_fd; 18 | 19 | char *timestamp() { 20 | struct tm *local; 21 | time_t t = time(NULL); 22 | char *str; 23 | 24 | /* Get the localtime */ 25 | local = localtime(&t); 26 | str = asctime(local); 27 | 28 | int i = 0; 29 | int len = strlen(str) + 1; 30 | 31 | for (i = 0; i < len; i++) { 32 | if (str[i] == '\n') { 33 | /* Move all the char following the char "\n" by one to the left. */ 34 | strncpy(&str[i], &str[i + 1], len - i); 35 | } 36 | } 37 | 38 | return str; 39 | } 40 | 41 | void sigchld_handler(int s) { 42 | /* waitpid() might overwrite errno, so we save and restore it: */ 43 | int saved_errno = errno; 44 | 45 | while (waitpid(-1, NULL, WNOHANG) > 0) 46 | ; 47 | errno = saved_errno; 48 | } 49 | 50 | #ifdef THREAD 51 | #include 52 | #define MAX_THREAD_COUNT 20 53 | struct args { 54 | int client_fd; 55 | }; 56 | int thread_count = -1; 57 | pthread_t threads_pool[MAX_THREAD_COUNT]; 58 | 59 | void kill_all_threads() { 60 | int killed_threads = 0; 61 | for (int i = 0; i <= thread_count; i++) { 62 | int return_val = pthread_cancel(threads_pool[i]); 63 | if (return_val != ESRCH) 64 | killed_threads++; 65 | } 66 | if (killed_threads) 67 | printf("\n[%s] SERVER: %d threads did not shutdown properly\n", timestamp(), 68 | killed_threads); 69 | else 70 | printf("\n[%s] All threads exited successfully\n", timestamp()); 71 | } 72 | void *service_clients(void *arguments) { 73 | 74 | struct args *p_args = (struct args *)arguments; 75 | 76 | /** 77 | * copy the client_fd locally as creation process ( genrerates new fd) of 78 | * a new thread will chage the value pointed by *argument 79 | */ 80 | 81 | int client_fd; 82 | 83 | client_fd = p_args->client_fd; 84 | 85 | printf("[%s] SERVER: Inside Thread %ld\n", timestamp(), pthread_self()); 86 | 87 | int bytes_sent; 88 | char buff[max_mssg_len]; 89 | 90 | char greetings[] = "SERVER: Hi client, you are now connected\n"; 91 | bytes_sent = send(client_fd, &greetings, sizeof(greetings), 0); 92 | if (bytes_sent == 0) { 93 | printf("[%s] SERVER: Connection lost with client(%d)\n", timestamp(), 94 | client_fd - 3); 95 | exit(EXIT_FAILURE); 96 | } else if (bytes_sent == -1) { 97 | perror("SERVER: send()"); 98 | exit(EXIT_FAILURE); 99 | } 100 | 101 | bzero(buff, max_mssg_len); 102 | 103 | while (1) { 104 | int bytes_rcvd; 105 | bytes_rcvd = recv(client_fd, &buff, sizeof(buff), 0); 106 | if (bytes_rcvd == 0) { 107 | printf("[%s] SERVER: Connection lost with client(%d)\n", timestamp(), 108 | client_fd - 3); 109 | break; 110 | } else if (bytes_rcvd == -1) { 111 | perror("SERVER: recv()"); 112 | break; 113 | } 114 | 115 | if (strncmp(buff, "!q", 2) == 0) { 116 | close(client_fd); 117 | printf("[%s] DISCONNECTED: CLIENT(%d)\n", timestamp(), client_fd - 3); 118 | printf("[%s] SERVER: Exiting from Thread %ld\n", timestamp(), 119 | pthread_self()); 120 | break; 121 | } 122 | 123 | fflush(stdout); 124 | printf("[%s] CLIENT_%d@host:~$%s", timestamp(), client_fd - 3, buff); 125 | bzero(buff, max_mssg_len); 126 | } 127 | 128 | /* Pthread_cancel() will clean up all the necessary things for us */ 129 | pthread_cancel(pthread_self()); 130 | } 131 | 132 | #endif 133 | 134 | void INTR_handler(int sig) { 135 | close(server_fd); 136 | printf("\n[%s] SERVER CLOSED\n", timestamp()); 137 | exit(0); 138 | } 139 | 140 | int main(int argc, char *argv[]) { 141 | int backlog; 142 | 143 | if (argc != 3) { 144 | puts("USAGE: "); 145 | exit(EXIT_FAILURE); 146 | } 147 | 148 | if (argv[1] == "" || argv[1] == NULL) { 149 | puts("ERROR: Enter a valid port number"); 150 | exit(EXIT_FAILURE); 151 | } 152 | 153 | if (argv[2] == "" || argv[2] == NULL) { 154 | puts("ERROR: Enter a valid backlog value"); 155 | exit(EXIT_FAILURE); 156 | } 157 | char *strptr; 158 | backlog = strtol(argv[2], &strptr, 10); 159 | 160 | struct addrinfo server_addr, *results, *p; 161 | struct sockaddr_in client_addr; 162 | socklen_t client_addr_size; 163 | 164 | int client_fd, server_status, bind_status, listen_status, accept_status, 165 | addr_status; 166 | char buff[max_mssg_len]; 167 | int n = 0, yes = 1; 168 | 169 | int bytes_sent; 170 | char addr[INET_ADDRSTRLEN]; 171 | 172 | memset(&server_addr, 0, sizeof(server_addr)); 173 | memset(&client_addr, 0, sizeof(client_addr)); 174 | 175 | /* 176 | struct addrinfo { 177 | int ai_flags; 178 | int ai_family; 179 | int ai_socktype; 180 | int ai_protocol; 181 | socklen_t ai_addrlen; 182 | struct sockaddr *ai_addr; 183 | char *ai_canonname; 184 | struct addrinfo *ai_next; 185 | }; 186 | */ 187 | 188 | server_addr.ai_family = PF_INET; /* IPv4 */ 189 | server_addr.ai_socktype = SOCK_STREAM; /* tcp Stream */ 190 | server_addr.ai_flags = AI_PASSIVE; /* fill ip automatically */ 191 | 192 | /* get all the available address of this machine */ 193 | 194 | if ((addr_status = getaddrinfo(NULL, argv[1], &server_addr, &results)) != 0) { 195 | printf("[%s] SERVER: ERROR getaddrinfo(): %s\n", timestamp(), 196 | gai_strerror(addr_status)); 197 | exit(EXIT_FAILURE); 198 | } 199 | 200 | /* bind a socket at the first available address */ 201 | for (p = results; p != NULL; p = p->ai_next) { 202 | 203 | inet_ntop(p->ai_family, p->ai_addr, addr, sizeof(addr)); 204 | printf("[%s] SERVER: Trying to build on: %s", timestamp(), addr); 205 | 206 | if ((server_fd = socket(p->ai_family, p->ai_socktype, p->ai_protocol)) == 207 | -1) { 208 | perror("ERROR socket()"); 209 | continue; /* if socket can not be created on this address try another */ 210 | } 211 | 212 | if (setsockopt(server_fd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(int)) == 213 | -1) { 214 | perror("ERROR setsockopt()"); 215 | exit(EXIT_FAILURE); 216 | } 217 | 218 | if (((bind_status = bind(server_fd, p->ai_addr, p->ai_addrlen)) == -1)) { 219 | perror("ERROR bind()"); 220 | continue; 221 | } 222 | 223 | /** 224 | * control reaches here if all the above conditions satifie 225 | * we have succesfully bound a socket and can exit from this loop 226 | */ 227 | 228 | break; 229 | } 230 | 231 | freeaddrinfo(results); 232 | 233 | /** 234 | * if we get p== NULL that means we couldn't bind to any of the addresses 235 | * should return from the program 236 | */ 237 | 238 | if (p == NULL) { 239 | puts("\nERROR: Couldn't build a server"); 240 | exit(EXIT_FAILURE); 241 | } 242 | 243 | if (listen_status = listen(server_fd, backlog) == -1) { 244 | perror("ERROR listen()"); 245 | exit(EXIT_FAILURE); 246 | } 247 | /* handle sigaction */ 248 | 249 | printf("\n[%s] SERVER: UP and LISTENING on %s:%s with BACKLOG %d\n", 250 | timestamp(), addr, argv[1], backlog); 251 | 252 | struct sigaction sa; 253 | sa.sa_handler = sigchld_handler; /* reap all dead processes */ 254 | sigemptyset(&sa.sa_mask); 255 | sa.sa_flags = SA_RESTART; 256 | 257 | if (sigaction(SIGCHLD, &sa, NULL) == -1) { 258 | perror("sigaction"); 259 | exit(1); 260 | } 261 | 262 | char greetings[] = "SERVER: Hi client, you are now connected\n"; 263 | 264 | #ifdef THREAD 265 | 266 | struct args thread_args; 267 | memset(&thread_args, 0, sizeof(thread_args)); 268 | #endif 269 | 270 | while (1) { 271 | signal(SIGINT, INTR_handler); 272 | 273 | inet_ntop(client_addr.sin_family, &client_addr.sin_addr.s_addr, addr, 274 | sizeof(addr)); 275 | 276 | client_fd = 277 | accept(server_fd, (struct sockaddr *)&client_addr, &client_addr_size); 278 | 279 | printf("[%s] SERVER: NEW CLIENT ID(%d): %s:%d\n", timestamp(), 280 | client_fd - 3, addr, ntohs(client_addr.sin_port)); 281 | char sorry[] = "SERVER: sorry could not give the service right now\n"; 282 | 283 | #ifdef PROCESS 284 | if (fork() == 0) { 285 | bytes_sent = send(client_fd, &greetings, sizeof(greetings), 0); 286 | if (bytes_sent == 0) { 287 | printf("[%s] SERVER: Connection lost with client(%d)\n", timestamp(), 288 | client_fd - 3); 289 | exit(EXIT_FAILURE); 290 | } else if (bytes_sent == -1) { 291 | perror("SERVER: send()"); 292 | exit(EXIT_FAILURE); 293 | } 294 | 295 | close(server_fd); 296 | bzero(buff, max_mssg_len); 297 | 298 | while (1) { 299 | int bytes_rcvd; 300 | 301 | bytes_rcvd = recv(client_fd, &buff, sizeof(buff), 0); 302 | if (bytes_rcvd == 0) { 303 | printf("[%s] SERVER: Connection lost with client(%d)\n", timestamp(), 304 | client_fd - 3); 305 | exit(EXIT_FAILURE); 306 | } else if (bytes_rcvd == -1) { 307 | perror("SERVER: recv()"); 308 | exit(EXIT_SUCCESS); // dont think its a failure 309 | } 310 | if (strncmp(buff, "!q", 2) == 0) { 311 | close(client_fd); 312 | printf("[%s] SERVER: DISCONNECTED: CLIENT(%d)\n", timestamp(), 313 | client_fd - 3); 314 | exit(EXIT_SUCCESS); 315 | } 316 | 317 | fflush(stdout); 318 | printf("[%s] CLIENT_%d@host:~$%s", timestamp(), client_fd - 3, buff); 319 | } 320 | } 321 | 322 | #endif 323 | 324 | #ifdef THREAD 325 | 326 | pthread_t t_id; 327 | 328 | thread_args.client_fd = client_fd; 329 | 330 | if (pthread_create(&t_id, NULL, service_clients, (void *)&thread_args) != 331 | 0) { 332 | printf("[%s] SERVER: ERROR in creating the Thread %ld\n", timestamp(), 333 | t_id); 334 | send(client_fd, sorry, sizeof(sorry), 0); 335 | close(client_fd); 336 | continue; 337 | } 338 | 339 | printf("[%s] SERVER: New thread created: %ld to service client %d\n", 340 | timestamp(), t_id, client_fd - 3); 341 | pthread_detach(t_id); 342 | threads_pool[++thread_count] = t_id; 343 | #endif 344 | } 345 | return 0; 346 | } 347 | -------------------------------------------------------------------------------- /action.yml: -------------------------------------------------------------------------------- 1 | name: "cppcheck-action" 2 | author: deep5050 3 | description: "Find potential vulnerabilities in your C/C++ codes" 4 | 5 | inputs: 6 | github_token: 7 | description: "GITHUB_TOKEN secret < automatically provided by Github , you don't need to set up >" 8 | required: true 9 | 10 | # github_username: 11 | # description: GitHub account name 12 | # default: "cppcheck-action" 13 | # github_email: 14 | # description: GitHub account email 15 | # default: "cppcheck-action@master" 16 | # commit_msg: 17 | # description: custom commit message 18 | # default: "cppcheck report added or updated" 19 | 20 | check_library: 21 | description: "Show information messages when library files have info." 22 | default: "disable" 23 | required: false 24 | 25 | skip_preprocessor: 26 | description: "Print preprocessor output on stdout and don't do any further processing." 27 | default: "disable" 28 | required: false 29 | 30 | enable: 31 | description: "Enable additional checks" 32 | default: "all" 33 | required: false 34 | 35 | exclude_check: 36 | description: "Give a source file or source file directory to exclude from the check" 37 | default: "disable" 38 | required: false 39 | 40 | inconclusive: 41 | description: " Allow that Cppcheck reports even though the analysis is inconclusive." 42 | default: "enable" 43 | required: false 44 | 45 | inline_suppression: 46 | description: "Enable inline suppressions" 47 | default: "disable" 48 | required: false 49 | 50 | force_language: 51 | description: "Forces cppcheck to check all files as the given language" 52 | default: "disable" 53 | required: false 54 | 55 | force: 56 | description: "Force checking of all configurations in files" 57 | default: "disable" 58 | required: false 59 | 60 | max_ctu_depth: 61 | description: "Max depth in whole program analysis" 62 | default: "disable" 63 | required: false 64 | 65 | platform: 66 | description: "Specifies platform specific types and sizes" 67 | default: "disable" 68 | required: false 69 | 70 | std: 71 | description: "Set the C/C++ standard" 72 | default: "c++20" 73 | required: false 74 | 75 | output_file: 76 | description: "file where the result to be dumped" 77 | default: "cppcheck_report.txt" 78 | required: false 79 | 80 | target_branch: 81 | description: "Branch that the badge will target. Defaults to the current branch." 82 | default: "" 83 | required: false 84 | 85 | other_options: 86 | description: "Any other options you want to add, separate with a space, wrong options will cause a failure" 87 | default: "disable" 88 | required: false 89 | 90 | pull_request_branch: 91 | description: "Branch that the action will target on pull_request. Defaults to GITHUB_BASE_REF." 92 | default: "" 93 | required: false 94 | 95 | target_repository: 96 | description: "Repository that the report will be pushed on. Defaults to the current repository." 97 | default: "" 98 | required: false 99 | 100 | pull_request_repository: 101 | description: "Repository that the action will target on pull_request. Defaults to TARGET_REPOSITORY" 102 | default: "" 103 | required: false 104 | 105 | runs: 106 | using: "docker" 107 | image: "Dockerfile" 108 | 109 | branding: 110 | icon: "check-circle" 111 | color: "red" 112 | -------------------------------------------------------------------------------- /cppcheck_report.txt: -------------------------------------------------------------------------------- 1 | __tests__/test.c:0:0: information: Too many #ifdef configurations - cppcheck only checks 1 of 3 configurations. Use --force to check all configurations. [toomanyconfigs] 2 | 3 | ^ 4 | __tests__/test.c:0:0: information: This file is not analyzed. Cppcheck failed to extract a valid configuration. Use -v for more details. [noValidConfiguration] 5 | 6 | ^ 7 | nofile:0:0: information: Cppcheck cannot find all the include files (use --check-config for details) [missingInclude] 8 | 9 | -------------------------------------------------------------------------------- /report.txt: -------------------------------------------------------------------------------- 1 | __tests__/client/client.c:285:13: style:inconclusive: Statements following return, break, continue, goto or throw will never be executed. [unreachableCode] 2 | stop_child_thread(); 3 | ^ 4 | __tests__/client/client.c:56:9: style: The scope of the variable 'rcvd_bytes' can be reduced. [variableScope] 5 | int rcvd_bytes; 6 | ^ 7 | __tests__/client/client.c:86:92: style: The scope of the variable 'n' can be reduced. [variableScope] 8 | int opt, port, debug_level, connect_status, sent_bytes, recv_bytes, temp_return_value, n; 9 | ^ 10 | __tests__/fibonacci.c:21:21: style: The scope of the variable 'first' can be reduced. [variableScope] 11 | static long int first = 0, second = 1, sum; 12 | ^ 13 | __tests__/fibonacci.c:21:32: style: The scope of the variable 'second' can be reduced. [variableScope] 14 | static long int first = 0, second = 1, sum; 15 | ^ 16 | __tests__/fibonacci.c:21:44: style: The scope of the variable 'sum' can be reduced. [variableScope] 17 | static long int first = 0, second = 1, sum; 18 | ^ 19 | __tests__/fibonacci.c:9:16: style: Variable 'i' is assigned a value that is never used. [unreadVariable] 20 | long int i = 0, j = 1; 21 | ^ 22 | __tests__/fibonacci.c:9:23: style: Variable 'j' is assigned a value that is never used. [unreadVariable] 23 | long int i = 0, j = 1; 24 | ^ 25 | __tests__/fibonacci.c:8:9: style: Unused variable: k [unusedVariable] 26 | int k, n; 27 | ^ 28 | __tests__/server/server.c:115:9: style: The scope of the variable 'client_fd' can be reduced. [variableScope] 29 | int client_fd, server_status, bind_status, listen_status, accept_status, 30 | ^ 31 | __tests__/server/server.c:115:35: style: The scope of the variable 'bind_status' can be reduced. [variableScope] 32 | int client_fd, server_status, bind_status, listen_status, accept_status, 33 | ^ 34 | __tests__/server/server.c:115:20: style: Unused variable: server_status [unusedVariable] 35 | int client_fd, server_status, bind_status, listen_status, accept_status, 36 | ^ 37 | __tests__/server/server.c:115:63: style: Unused variable: accept_status [unusedVariable] 38 | int client_fd, server_status, bind_status, listen_status, accept_status, 39 | ^ 40 | __tests__/server/server.c:116:38: style: Unused variable: bytes_sent [unusedVariable] 41 | addr_status, n = 0, yes = 1, bytes_sent; 42 | ^ 43 | __tests__/server/server.c:130:10: style: Unused variable: buff [unusedVariable] 44 | char buff[MAX_MSG_LEN], addr[INET_ADDRSTRLEN]; 45 | ^ 46 | __tests__/test.c:26:9: style: Obsolete function 'asctime' called. It is recommended to use 'strftime' instead. [asctimeCalled] 47 | str = asctime(local); 48 | ^ 49 | __tests__/test.c:243:6: style: Suspicious condition (assignment + comparison); Clarify expression with parentheses. [clarifyCondition] 50 | if (listen_status = listen(server_fd, backlog) == -1) { 51 | ^ 52 | __tests__/test.c:243:21: style: Variable 'listen_status' is assigned a value that is never used. [unreadVariable] 53 | if (listen_status = listen(server_fd, backlog) == -1) { 54 | ^ 55 | __tests__/test.c:262:20: style: Variable 'greetings' is assigned a value that is never used. [unreadVariable] 56 | char greetings[] = "SERVER: Hi client, you are now connected\n"; 57 | ^ 58 | __tests__/test.c:164:18: style: Unused variable: server_status [unusedVariable] 59 | int client_fd, server_status, bind_status, listen_status, accept_status, 60 | ^ 61 | __tests__/test.c:164:61: style: Unused variable: accept_status [unusedVariable] 62 | int client_fd, server_status, bind_status, listen_status, accept_status, 63 | ^ 64 | __tests__/test.c:166:8: style: Unused variable: buff [unusedVariable] 65 | char buff[max_mssg_len]; 66 | ^ 67 | __tests__/test.c:169:7: style: Unused variable: bytes_sent [unusedVariable] 68 | int bytes_sent; 69 | ^ 70 | nofile:0:0: information: Cppcheck cannot find all the include files (use --check-config for details) [missingInclude] 71 | 72 | -------------------------------------------------------------------------------- /src/entrypoint.py: -------------------------------------------------------------------------------- 1 | """Drive the parameter collection and execution for cppcheck.""" 2 | import operator 3 | import os 4 | import subprocess 5 | import sys 6 | 7 | ENCODING = "utf-8" 8 | SCA_EXECUTOR = "cppcheck" 9 | DISPLAY_SCA_VERSION = True 10 | DISPLAY_SCA_HELP = True 11 | SOURCE_ROOT = "." 12 | 13 | # The following environment reads will fail execution if variables not set: 14 | GITHUB_EVENT_NAME = os.environ["GITHUB_EVENT_NAME"] 15 | # Set repository 16 | CURRENT_REPOSITORY = os.environ["GITHUB_REPOSITORY"] 17 | # Set branches 18 | GITHUB_REF = os.environ["GITHUB_REF"] 19 | GITHUB_HEAD_REF = os.environ["GITHUB_HEAD_REF"] 20 | GITHUB_BASE_REF = os.environ["GITHUB_BASE_REF"] 21 | # Owners and tokens 22 | GITHUB_ACTOR = os.environ["GITHUB_ACTOR"] 23 | GITHUB_REPOSITORY_OWNER = os.environ["GITHUB_REPOSITORY_OWNER"] 24 | INPUT_GITHUB_TOKEN = os.environ["INPUT_GITHUB_TOKEN"] 25 | 26 | # Derive from environment with defaults: 27 | # TODO: How about PRs from forks? 28 | INPUT_TARGET_REPOSITORY = os.getenv("INPUT_TARGET_REPOSITORY", CURRENT_REPOSITORY) 29 | INPUT_PULL_REQUEST_REPOSITORY = os.getenv( 30 | "INPUT_PULL_REQUEST_REPOSITORY", INPUT_TARGET_REPOSITORY 31 | ) 32 | REPOSITORY = ( 33 | INPUT_PULL_REQUEST_REPOSITORY 34 | if GITHUB_EVENT_NAME == "pull_request" 35 | else INPUT_TARGET_REPOSITORY 36 | ) 37 | 38 | CURRENT_BRANCH = GITHUB_HEAD_REF or GITHUB_REF.rsplit("/", 1)[-1] 39 | INPUT_TARGET_BRANCH = os.getenv("INPUT_TARGET_BRANCH", CURRENT_BRANCH) 40 | INPUT_PULL_REQUEST_BRANCH = os.getenv("INPUT_PULL_REQUEST_BRANCH", GITHUB_BASE_REF) 41 | BRANCH = ( 42 | INPUT_PULL_REQUEST_BRANCH 43 | if GITHUB_EVENT_NAME == "pull_request" 44 | else INPUT_TARGET_BRANCH 45 | ) 46 | 47 | 48 | # Define cppcheck specific vocabulary for switches: 49 | DISABLED = "disable" 50 | ENABLED = "enable" 51 | CHECK_EVERYTHING = "all" 52 | 53 | CHECKS_SEP = "," 54 | KNOWN_CHECKS = ( 55 | CHECK_EVERYTHING, 56 | "information", 57 | "missingInclude", 58 | "performance", 59 | "portability", 60 | "style", 61 | "unusedFunction", 62 | "warning", 63 | ) 64 | OTHERS_SEP = " -" 65 | 66 | # Domain specific mapping between environment and cppcheck parameters: 67 | CHECK_LIBRARY = "INPUT_CHECK_LIBRARY" 68 | SKIP_PREPROCESSOR = "INPUT_SKIP_PREPROCESSOR" 69 | ENABLE_CHECKS = "INPUT_ENABLE" 70 | EXCLUDE_CHECK = "INPUT_EXCLUDE_CHECK" 71 | ENABLE_INCONCLUSIVE = "INPUT_INCONCLUSIVE" 72 | FORCE = "INPUT_FORCE" 73 | INLINE_SUPPRESSION = "INPUT_INLINE_SUPPRESSION" 74 | ENFORCE_LANGUAGE = "INPUT_FORCE_LANGUAGE" 75 | MAX_CTU_DEPTH = "INPUT_MAX_CTU_DEPTH" 76 | OUTPUT_FILE = "INPUT_OUTPUT_FILE" 77 | PLATFORM_TYPE = "INPUT_PLATFORM" 78 | STD = "INPUT_STD" 79 | OTHER_OPTIONS = "INPUT_OTHER_OPTIONS" 80 | 81 | 82 | # Main interface map for cppcheck instrumentation and outputs: 83 | DSL = { 84 | CHECK_LIBRARY: os.getenv(CHECK_LIBRARY, DISABLED), 85 | SKIP_PREPROCESSOR: os.getenv(SKIP_PREPROCESSOR, DISABLED), 86 | ENABLE_CHECKS: os.getenv(ENABLE_CHECKS, CHECK_EVERYTHING), 87 | EXCLUDE_CHECK: os.getenv(EXCLUDE_CHECK, DISABLED), 88 | ENABLE_INCONCLUSIVE: os.getenv(ENABLE_INCONCLUSIVE, ENABLED), 89 | FORCE: os.getenv(FORCE, DISABLED), 90 | INLINE_SUPPRESSION: os.getenv(INLINE_SUPPRESSION, DISABLED), 91 | ENFORCE_LANGUAGE: os.getenv(ENFORCE_LANGUAGE, DISABLED), 92 | MAX_CTU_DEPTH: os.getenv(MAX_CTU_DEPTH, DISABLED), 93 | OUTPUT_FILE: os.getenv(OUTPUT_FILE, "cppcheck_report.txt"), 94 | PLATFORM_TYPE: os.getenv(PLATFORM_TYPE, DISABLED), 95 | STD: os.getenv(STD, DISABLED), 96 | OTHER_OPTIONS: os.getenv(OTHER_OPTIONS, DISABLED), 97 | } 98 | 99 | 100 | def split_other_options(text): 101 | """Naive split of other options as space-dash separated entries yielding single options.""" 102 | if OTHERS_SEP in text: 103 | is_first = True 104 | for entry in text.split(OTHERS_SEP): 105 | yield entry.strip() if is_first else f'-{entry.strip()}' # other entries lose dash 106 | is_first = False 107 | else: 108 | yield text.strip() 109 | 110 | 111 | 112 | # Prepare actions to be taken using the above environment interface map: 113 | CONSTANT_ACTIONS = 4 114 | ACTIONS = { # group by arity of actions to simplify processing below 115 | # constant actions: 116 | CHECK_LIBRARY: (operator.eq, ENABLED, "--check-library", None), 117 | SKIP_PREPROCESSOR: (operator.eq, ENABLED, "-E", None), 118 | INLINE_SUPPRESSION: (operator.eq, ENABLED, "--inline-suppr", None), 119 | ENABLE_INCONCLUSIVE: (operator.ne, DISABLED, "--inconclusive", None), 120 | FORCE: (operator.ne, DISABLED, "--force", None), 121 | # unary actions: 122 | EXCLUDE_CHECK: (operator.ne, DISABLED, "-i{}", None), # Newer versions of cppcheck (>1.9) do not accept a space here 123 | ENFORCE_LANGUAGE: (operator.ne, DISABLED, "--language={}", None), 124 | MAX_CTU_DEPTH: (operator.ne, DISABLED, "--max-ctu-depth={}", None), 125 | PLATFORM_TYPE: (operator.ne, DISABLED, "--platform={}", None), 126 | STD: (operator.ne, DISABLED, "--std={}", None), 127 | OTHER_OPTIONS: (operator.ne, DISABLED, "{}", split_other_options), 128 | } 129 | CONSTANT_DIMENSIONS = tuple(ACTIONS.keys())[:CONSTANT_ACTIONS] 130 | 131 | CPPCHECK_NO_PATHS_OPENED_INDICATOR = ( 132 | "cppcheck: error: could not find or open any of the paths given." 133 | ) 134 | 135 | 136 | def split_csv(text): 137 | """Naive split of text as comma separated check aspects yielding as-input case strings.""" 138 | if CHECKS_SEP in text: 139 | for check in text.split(CHECKS_SEP): 140 | yield check.strip() 141 | else: 142 | yield text.strip() 143 | 144 | 145 | def is_valid(check): 146 | """Return scope if valid else empty string.""" 147 | return check if check in KNOWN_CHECKS else "" 148 | 149 | 150 | def parse_checks(dsl): 151 | """Return the parsed checks.""" 152 | checks = set(t for t in split_csv(dsl[ENABLE_CHECKS]) if is_valid(t)) 153 | if CHECK_EVERYTHING in checks: 154 | checks = [CHECK_EVERYTHING] 155 | else: 156 | checks = sorted(checks) 157 | return checks 158 | 159 | 160 | def command(dsl=None, actions=None, checks_sep=CHECKS_SEP, constant_dimensions=CONSTANT_DIMENSIONS): 161 | """Prepare the command vector and set the path to the report file""" 162 | dsl = DSL if dsl is None else dsl 163 | actions = ACTIONS if actions is None else actions 164 | 165 | vector = [ 166 | SCA_EXECUTOR, 167 | f"--enable={checks_sep.join(parse_checks(dsl))}", 168 | ] 169 | 170 | for dim in actions: 171 | predicate, ref, template, processing = actions[dim] 172 | payload = dsl[dim] 173 | if predicate(payload, ref): 174 | if not processing: 175 | vector.append(template if dim in constant_dimensions else template.format(payload)) 176 | else: # implicit dim not in constant_dimension 177 | for chunk in processing(payload): 178 | vector.append(template.format(chunk)) 179 | 180 | 181 | return vector 182 | 183 | 184 | def display_sca_executor_version(): 185 | """Capture current behavior and document tool version.""" 186 | return subprocess.run((SCA_EXECUTOR, "--version"), capture_output=True, check=False) 187 | 188 | 189 | def display_sca_executor_help(): 190 | """Capture current behavior and document tool version.""" 191 | return subprocess.run((SCA_EXECUTOR, "--help"), capture_output=True, check=False) 192 | 193 | 194 | def run(vector, where=SOURCE_ROOT, show_version=False, show_help=False): 195 | """Execute the command in a sub process.""" 196 | if show_version: 197 | print("retrieving cppcheck version") 198 | completed = display_sca_executor_version() 199 | print(" ", completed.stdout.decode(ENCODING, errors="ignore").strip()) 200 | 201 | if show_help: 202 | print("retrieving cppcheck help") 203 | completed = display_sca_executor_help() 204 | for line in completed.stdout.decode(ENCODING, errors="ignore").split("\n"): 205 | print(" ", line) 206 | 207 | vector.append(f"--output-file={DSL[OUTPUT_FILE]}") 208 | vector.append(f"{where}") 209 | print("executing static code analysis") 210 | print(f" effective command: {' '.join(vector)}") 211 | print("output from analysis") 212 | try: 213 | completed = subprocess.run(vector, capture_output=True, check=True) 214 | except FileNotFoundError as err: 215 | print("command not found?", err) 216 | return 1 217 | except subprocess.CalledProcessError as err: 218 | print("source root not found?", err) 219 | print("details:") 220 | print(err.stdout.decode(ENCODING, errors="ignore")) 221 | return 1 222 | 223 | if not completed.returncode: # currently cppcheck is happy to find no source file 224 | print("errors from execution") 225 | 226 | lines = completed.stdout.decode(ENCODING, errors="ignore").split("\n") 227 | 228 | for line in lines: 229 | print(" ", line) 230 | 231 | if lines[0].strip() == CPPCHECK_NO_PATHS_OPENED_INDICATOR: 232 | print("no source files found during execution?") 233 | 234 | if completed.stderr: 235 | print("captured output on standard error:") 236 | for line in completed.stderr.decode(ENCODING, errors="ignore").split("\n"): 237 | print(" ", line) 238 | return None 239 | 240 | 241 | def main(): 242 | """Drive the parameter extraction and execution of cppcheck.""" 243 | if all((GITHUB_EVENT_NAME == "pull_request", GITHUB_ACTOR != GITHUB_REPOSITORY_OWNER)): 244 | return 2 245 | 246 | return run(command(), SOURCE_ROOT, DISPLAY_SCA_VERSION, DISPLAY_SCA_HELP) 247 | 248 | 249 | if __name__ == "__main__": 250 | sys.exit(main()) # pragma: no cover 251 | --------------------------------------------------------------------------------