File: | pr/Linux4.19_x86_64_gcc_glibc_PTH_64_DBG.OBJ/pr/tests/../../../pr/tests/tmoacc.c |
Warning: | line 149, column 33 Array access (from variable 'buffer') results in a null pointer dereference |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
1 | /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ | |||
2 | /* This Source Code Form is subject to the terms of the Mozilla Public | |||
3 | * License, v. 2.0. If a copy of the MPL was not distributed with this | |||
4 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ | |||
5 | ||||
6 | #include "nspr.h" | |||
7 | ||||
8 | #include <stdlib.h> | |||
9 | #include <string.h> | |||
10 | ||||
11 | #include "plerror.h" | |||
12 | #include "plgetopt.h" | |||
13 | ||||
14 | #ifdef DEBUG1 | |||
15 | #define PORT_INC_DO+100 +100 | |||
16 | #else | |||
17 | #define PORT_INC_DO+100 | |||
18 | #endif | |||
19 | #ifdef IS_64 | |||
20 | #define PORT_INC_3264+200 +200 | |||
21 | #else | |||
22 | #define PORT_INC_3264+200 | |||
23 | #endif | |||
24 | ||||
25 | #define BASE_PORT9867 +100 +200 9867 PORT_INC_DO+100 PORT_INC_3264+200 | |||
26 | #define DEFAULT_THREADS1 1 | |||
27 | #define DEFAULT_BACKLOG10 10 | |||
28 | #define DEFAULT_TIMEOUT10 10 | |||
29 | #define RANDOM_RANGE100 100 /* should be significantly smaller than RAND_MAX */ | |||
30 | ||||
31 | typedef enum {running, stopped} Status; | |||
32 | ||||
33 | typedef struct Shared | |||
34 | { | |||
35 | PRLock *ml; | |||
36 | PRCondVar *cv; | |||
37 | PRBool passed; | |||
38 | PRBool random; | |||
39 | PRFileDesc *debug; | |||
40 | PRIntervalTime timeout; | |||
41 | PRFileDesc *listenSock; | |||
42 | Status status; | |||
43 | } Shared; | |||
44 | ||||
45 | static PRIntervalTime Timeout(const Shared *shared) | |||
46 | { | |||
47 | PRIntervalTime timeout = shared->timeout; | |||
48 | if (shared->random) | |||
49 | { | |||
50 | PRIntervalTime half = timeout >> 1; /* one half of the interval */ | |||
51 | PRIntervalTime quarter = half >> 1; /* one quarter of the interval */ | |||
52 | /* something in [0..timeout / 2) */ | |||
53 | PRUint32 random = (rand() % RANDOM_RANGE100) * half / RANDOM_RANGE100; | |||
54 | timeout = (3 * quarter) + random; /* [75..125)% */ | |||
55 | } | |||
56 | return timeout; | |||
57 | } /* Timeout */ | |||
58 | ||||
59 | static void Accept(void *arg) | |||
60 | { | |||
61 | PRStatus rv; | |||
62 | char *buffer = NULL((void*)0); | |||
| ||||
63 | PRNetAddr clientAddr; | |||
64 | Shared *shared = (Shared*)arg; | |||
65 | PRInt32 recv_length = 0, flags = 0; | |||
66 | PRFileDesc *clientSock; | |||
67 | PRIntn toread, byte, bytes, loop = 0; | |||
68 | struct Descriptor { | |||
69 | PRInt32 length; | |||
70 | PRUint32 checksum; | |||
71 | } descriptor; | |||
72 | ||||
73 | do | |||
74 | { | |||
75 | PRUint32 checksum = 0; | |||
76 | if (NULL((void*)0) != shared->debug) { | |||
77 | PR_fprintf(shared->debug, "[%d]accepting ... ", loop++); | |||
78 | } | |||
79 | clientSock = PR_Accept( | |||
80 | shared->listenSock, &clientAddr, Timeout(shared)); | |||
81 | if (clientSock != NULL((void*)0)) | |||
82 | { | |||
83 | if (NULL((void*)0) != shared->debug) { | |||
84 | PR_fprintf(shared->debug, "reading length ... "); | |||
85 | } | |||
86 | bytes = PR_Recv( | |||
87 | clientSock, &descriptor, sizeof(descriptor), | |||
88 | flags, Timeout(shared)); | |||
89 | if (sizeof(descriptor) == bytes) | |||
90 | { | |||
91 | /* and, before doing something stupid ... */ | |||
92 | descriptor.length = PR_ntohl(descriptor.length); | |||
93 | descriptor.checksum = PR_ntohl(descriptor.checksum); | |||
94 | if (NULL((void*)0) != shared->debug) { | |||
95 | PR_fprintf(shared->debug, "%d bytes ... ", descriptor.length); | |||
96 | } | |||
97 | toread = descriptor.length; | |||
98 | if (recv_length < descriptor.length) | |||
99 | { | |||
100 | if (NULL((void*)0) != buffer) { | |||
101 | PR_DELETE(buffer){ PR_Free(buffer); (buffer) = ((void*)0); }; | |||
102 | } | |||
103 | buffer = (char*)PR_MALLOC(descriptor.length)(PR_Malloc((descriptor.length))); | |||
104 | recv_length = descriptor.length; | |||
105 | } | |||
106 | for (toread = descriptor.length; toread > 0; toread -= bytes) | |||
107 | { | |||
108 | bytes = PR_Recv( | |||
109 | clientSock, &buffer[descriptor.length - toread], | |||
110 | toread, flags, Timeout(shared)); | |||
111 | if (-1 == bytes) | |||
112 | { | |||
113 | if (NULL((void*)0) != shared->debug) { | |||
114 | PR_fprintf(shared->debug, "read data failed..."); | |||
115 | } | |||
116 | bytes = 0; | |||
117 | } | |||
118 | } | |||
119 | } | |||
120 | else if (NULL((void*)0) != shared->debug) | |||
121 | { | |||
122 | PR_fprintf(shared->debug, "read desciptor failed..."); | |||
123 | descriptor.length = -1; | |||
124 | } | |||
125 | if (NULL((void*)0) != shared->debug) { | |||
126 | PR_fprintf(shared->debug, "closing"); | |||
127 | } | |||
128 | rv = PR_Shutdown(clientSock, PR_SHUTDOWN_BOTH); | |||
129 | if ((PR_FAILURE == rv) && (NULL((void*)0) != shared->debug)) | |||
130 | { | |||
131 | PR_fprintf(shared->debug, " failed"); | |||
132 | shared->passed = PR_FALSE0; | |||
133 | } | |||
134 | rv = PR_Close(clientSock); | |||
135 | if (PR_FAILURE == rv) if (NULL((void*)0) != shared->debug) | |||
136 | { | |||
137 | PR_fprintf(shared->debug, " failed"); | |||
138 | shared->passed = PR_FALSE0; | |||
139 | } | |||
140 | if (descriptor.length > 0) | |||
141 | { | |||
142 | for (byte = 0; byte
| |||
143 | { | |||
144 | PRUint32 overflow = checksum & 0x80000000; | |||
145 | checksum = (checksum << 1); | |||
146 | if (0x00000000 != overflow
| |||
147 | checksum += 1; | |||
148 | } | |||
149 | checksum += buffer[byte]; | |||
| ||||
150 | } | |||
151 | if ((descriptor.checksum != checksum) && (NULL((void*)0) != shared->debug)) | |||
152 | { | |||
153 | PR_fprintf(shared->debug, " ... data mismatch"); | |||
154 | shared->passed = PR_FALSE0; | |||
155 | } | |||
156 | } | |||
157 | else if (0 == descriptor.length) | |||
158 | { | |||
159 | PR_Lock(shared->ml); | |||
160 | shared->status = stopped; | |||
161 | PR_NotifyCondVar(shared->cv); | |||
162 | PR_Unlock(shared->ml); | |||
163 | } | |||
164 | if (NULL((void*)0) != shared->debug) { | |||
165 | PR_fprintf(shared->debug, "\n"); | |||
166 | } | |||
167 | } | |||
168 | else | |||
169 | { | |||
170 | if (PR_PENDING_INTERRUPT_ERROR(-5993L) != PR_GetError()) | |||
171 | { | |||
172 | if (NULL((void*)0) != shared->debug) { | |||
173 | PL_PrintError("Accept"); | |||
174 | } | |||
175 | shared->passed = PR_FALSE0; | |||
176 | } | |||
177 | } | |||
178 | } while (running == shared->status); | |||
179 | if (NULL((void*)0) != buffer) { | |||
180 | PR_DELETE(buffer){ PR_Free(buffer); (buffer) = ((void*)0); }; | |||
181 | } | |||
182 | } /* Accept */ | |||
183 | ||||
184 | PRIntn Tmoacc(PRIntn argc, char **argv) | |||
185 | { | |||
186 | PRStatus rv; | |||
187 | PRIntn exitStatus; | |||
188 | PRIntn index; | |||
189 | Shared *shared; | |||
190 | PLOptStatus os; | |||
191 | PRThread **thread; | |||
192 | PRNetAddr listenAddr; | |||
193 | PRSocketOptionData sockOpt; | |||
194 | PRIntn timeout = DEFAULT_TIMEOUT10; | |||
195 | PRIntn threads = DEFAULT_THREADS1; | |||
196 | PRIntn backlog = DEFAULT_BACKLOG10; | |||
197 | PRThreadScope thread_scope = PR_LOCAL_THREAD; | |||
198 | ||||
199 | PLOptState *opt = PL_CreateOptState(argc, argv, "dGb:t:T:R"); | |||
200 | ||||
201 | shared = PR_NEWZAP(Shared)((Shared*)PR_Calloc(1, sizeof(Shared))); | |||
202 | ||||
203 | shared->debug = NULL((void*)0); | |||
204 | shared->passed = PR_TRUE1; | |||
205 | shared->random = PR_TRUE1; | |||
206 | shared->status = running; | |||
207 | shared->ml = PR_NewLock(); | |||
208 | shared->cv = PR_NewCondVar(shared->ml); | |||
209 | ||||
210 | while (PL_OPT_EOL != (os = PL_GetNextOpt(opt))) | |||
211 | { | |||
212 | if (PL_OPT_BAD == os) { | |||
213 | continue; | |||
214 | } | |||
215 | switch (opt->option) | |||
216 | { | |||
217 | case 'd': /* debug mode */ | |||
218 | shared->debug = PR_GetSpecialFD(PR_StandardError); | |||
219 | break; | |||
220 | case 'G': /* use global threads */ | |||
221 | thread_scope = PR_GLOBAL_THREAD; | |||
222 | break; | |||
223 | case 'b': /* size of listen backlog */ | |||
224 | backlog = atoi(opt->value); | |||
225 | break; | |||
226 | case 't': /* number of threads doing accept */ | |||
227 | threads = atoi(opt->value); | |||
228 | break; | |||
229 | case 'T': /* timeout used for network operations */ | |||
230 | timeout = atoi(opt->value); | |||
231 | break; | |||
232 | case 'R': /* randomize the timeout values */ | |||
233 | shared->random = PR_TRUE1; | |||
234 | break; | |||
235 | default: | |||
236 | break; | |||
237 | } | |||
238 | } | |||
239 | PL_DestroyOptState(opt); | |||
240 | if (0 == threads) { | |||
241 | threads = DEFAULT_THREADS1; | |||
242 | } | |||
243 | if (0 == backlog) { | |||
244 | backlog = DEFAULT_BACKLOG10; | |||
245 | } | |||
246 | if (0 == timeout) { | |||
247 | timeout = DEFAULT_TIMEOUT10; | |||
248 | } | |||
249 | ||||
250 | PR_STDIO_INIT(); | |||
251 | memset(&listenAddr, 0, sizeof(listenAddr)); | |||
252 | rv = PR_InitializeNetAddr(PR_IpAddrAny, BASE_PORT9867 +100 +200, &listenAddr); | |||
253 | PR_ASSERT(PR_SUCCESS == rv)((PR_SUCCESS == rv)?((void)0):PR_Assert("PR_SUCCESS == rv","../../../pr/tests/tmoacc.c" ,253)); | |||
254 | ||||
255 | shared->timeout = PR_SecondsToInterval(timeout); | |||
256 | ||||
257 | /* First bind to the socket */ | |||
258 | shared->listenSock = PR_NewTCPSocket(); | |||
259 | if (shared->listenSock) | |||
260 | { | |||
261 | sockOpt.option = PR_SockOpt_Reuseaddr; | |||
262 | sockOpt.value.reuse_addr = PR_TRUE1; | |||
263 | rv = PR_SetSocketOption(shared->listenSock, &sockOpt); | |||
264 | PR_ASSERT(PR_SUCCESS == rv)((PR_SUCCESS == rv)?((void)0):PR_Assert("PR_SUCCESS == rv","../../../pr/tests/tmoacc.c" ,264)); | |||
265 | rv = PR_Bind(shared->listenSock, &listenAddr); | |||
266 | if (rv != PR_FAILURE) | |||
267 | { | |||
268 | rv = PR_Listen(shared->listenSock, threads + backlog); | |||
269 | if (PR_SUCCESS == rv) | |||
270 | { | |||
271 | thread = (PRThread**)PR_CALLOC(threads * sizeof(PRThread*))(PR_Calloc(1, (threads * sizeof(PRThread*)))); | |||
272 | for (index = 0; index < threads; ++index) | |||
273 | { | |||
274 | thread[index] = PR_CreateThread( | |||
275 | PR_USER_THREAD, Accept, shared, | |||
276 | PR_PRIORITY_NORMAL, thread_scope, | |||
277 | PR_JOINABLE_THREAD, 0); | |||
278 | PR_ASSERT(NULL != thread[index])((((void*)0) != thread[index])?((void)0):PR_Assert("NULL != thread[index]" ,"../../../pr/tests/tmoacc.c",278)); | |||
279 | } | |||
280 | ||||
281 | PR_Lock(shared->ml); | |||
282 | while (shared->status == running) { | |||
283 | PR_WaitCondVar(shared->cv, PR_INTERVAL_NO_TIMEOUT0xffffffffUL); | |||
284 | } | |||
285 | PR_Unlock(shared->ml); | |||
286 | for (index = 0; index < threads; ++index) | |||
287 | { | |||
288 | rv = PR_Interrupt(thread[index]); | |||
289 | PR_ASSERT(PR_SUCCESS== rv)((PR_SUCCESS== rv)?((void)0):PR_Assert("PR_SUCCESS== rv","../../../pr/tests/tmoacc.c" ,289)); | |||
290 | rv = PR_JoinThread(thread[index]); | |||
291 | PR_ASSERT(PR_SUCCESS== rv)((PR_SUCCESS== rv)?((void)0):PR_Assert("PR_SUCCESS== rv","../../../pr/tests/tmoacc.c" ,291)); | |||
292 | } | |||
293 | PR_DELETE(thread){ PR_Free(thread); (thread) = ((void*)0); }; | |||
294 | } | |||
295 | else | |||
296 | { | |||
297 | if (shared->debug) { | |||
298 | PL_PrintError("Listen"); | |||
299 | } | |||
300 | shared->passed = PR_FALSE0; | |||
301 | } | |||
302 | } | |||
303 | else | |||
304 | { | |||
305 | if (shared->debug) { | |||
306 | PL_PrintError("Bind"); | |||
307 | } | |||
308 | shared->passed = PR_FALSE0; | |||
309 | } | |||
310 | ||||
311 | PR_Close(shared->listenSock); | |||
312 | } | |||
313 | else | |||
314 | { | |||
315 | if (shared->debug) { | |||
316 | PL_PrintError("Create"); | |||
317 | } | |||
318 | shared->passed = PR_FALSE0; | |||
319 | } | |||
320 | ||||
321 | PR_DestroyCondVar(shared->cv); | |||
322 | PR_DestroyLock(shared->ml); | |||
323 | ||||
324 | PR_fprintf( | |||
325 | PR_GetSpecialFD(PR_StandardError), "%s\n", | |||
326 | ((shared->passed) ? "PASSED" : "FAILED")); | |||
327 | ||||
328 | exitStatus = (shared->passed) ? 0 : 1; | |||
329 | PR_DELETE(shared){ PR_Free(shared); (shared) = ((void*)0); }; | |||
330 | return exitStatus; | |||
331 | } | |||
332 | ||||
333 | int main(int argc, char **argv) | |||
334 | { | |||
335 | return (PR_VersionCheck(PR_VERSION"4.36 Beta")) ? | |||
336 | PR_Initialize(Tmoacc, argc, argv, 4) : -1; | |||
337 | } /* main */ | |||
338 | ||||
339 | /* tmoacc */ |