Every call to swprintf is followed by line which adds nul terminator. This
patch
introduces openvpn_swprintf() which guarantees nul termination for size >
0.
Same approach as for snprintf / openvpn_snprintf.
Signed-off-by: Lev Stipakov <lev@openvpn.net>
Acked-by: Selva Nair <selva.nair@gmail.com>
Message-Id: <1540203571-17646-1-git-send-email-lstipakov@gmail.com>
URL: https://www.mail-archive.com/openvpn-devel@lists.sourceforge.net/msg17786.html
Signed-off-by: Gert Doering <gert@greenie.muc.de>
... | ... |
@@ -37,6 +37,8 @@ |
37 | 37 |
|
38 | 38 |
#include "memdbg.h" |
39 | 39 |
|
40 |
+#include <wchar.h> |
|
41 |
+ |
|
40 | 42 |
size_t |
41 | 43 |
array_mult_safe(const size_t m1, const size_t m2, const size_t extra) |
42 | 44 |
{ |
... | ... |
@@ -308,6 +310,21 @@ openvpn_snprintf(char *str, size_t size, const char *format, ...) |
308 | 308 |
return (len >= 0 && len < size); |
309 | 309 |
} |
310 | 310 |
|
311 |
+bool |
|
312 |
+openvpn_swprintf(wchar_t *const str, const size_t size, const wchar_t *const format, ...) |
|
313 |
+{ |
|
314 |
+ va_list arglist; |
|
315 |
+ int len = -1; |
|
316 |
+ if (size > 0) |
|
317 |
+ { |
|
318 |
+ va_start(arglist, format); |
|
319 |
+ len = vswprintf(str, size, format, arglist); |
|
320 |
+ va_end(arglist); |
|
321 |
+ str[size - 1] = L'\0'; |
|
322 |
+ } |
|
323 |
+ return (len >= 0 && len < size); |
|
324 |
+} |
|
325 |
+ |
|
311 | 326 |
/* |
312 | 327 |
* write a string to the end of a buffer that was |
313 | 328 |
* truncated by buf_printf |
... | ... |
@@ -448,6 +448,17 @@ __attribute__ ((format(__printf__, 3, 4))) |
448 | 448 |
#endif |
449 | 449 |
; |
450 | 450 |
|
451 |
+ |
|
452 |
+/* |
|
453 |
+ * Like swprintf but guarantees null termination for size > 0 |
|
454 |
+ */ |
|
455 |
+bool |
|
456 |
+openvpn_swprintf(wchar_t *const str, const size_t size, const wchar_t *const format, ...); |
|
457 |
+/* |
|
458 |
+ * Unlike in openvpn_snprintf, we cannot use format attributes since |
|
459 |
+ * GCC doesn't support wprintf as archetype. |
|
460 |
+ */ |
|
461 |
+ |
|
451 | 462 |
/* |
452 | 463 |
* remove/add trailing characters |
453 | 464 |
*/ |
... | ... |
@@ -4472,8 +4472,7 @@ get_adapter_index_method_1(const char *guid) |
4472 | 4472 |
DWORD index; |
4473 | 4473 |
ULONG aindex; |
4474 | 4474 |
wchar_t wbuf[256]; |
4475 |
- swprintf(wbuf, SIZE(wbuf), L"\\DEVICE\\TCPIP_%S", guid); |
|
4476 |
- wbuf [SIZE(wbuf) - 1] = 0; |
|
4475 |
+ openvpn_swprintf(wbuf, SIZE(wbuf), L"\\DEVICE\\TCPIP_%S", guid); |
|
4477 | 4476 |
if (GetAdapterIndex(wbuf, &aindex) != NO_ERROR) |
4478 | 4477 |
{ |
4479 | 4478 |
index = TUN_ADAPTER_INDEX_INVALID; |
... | ... |
@@ -57,6 +57,21 @@ openvpn_sntprintf(LPTSTR str, size_t size, LPCTSTR format, ...) |
57 | 57 |
return res; |
58 | 58 |
} |
59 | 59 |
|
60 |
+BOOL |
|
61 |
+openvpn_swprintf(wchar_t *const str, const size_t size, const wchar_t *const format, ...) |
|
62 |
+{ |
|
63 |
+ va_list arglist; |
|
64 |
+ int len = -1; |
|
65 |
+ if (size > 0) |
|
66 |
+ { |
|
67 |
+ va_start(arglist, format); |
|
68 |
+ len = vswprintf(str, size, format, arglist); |
|
69 |
+ va_end(arglist); |
|
70 |
+ str[size - 1] = L'\0'; |
|
71 |
+ } |
|
72 |
+ return (len >= 0 && len < size); |
|
73 |
+} |
|
74 |
+ |
|
60 | 75 |
static DWORD |
61 | 76 |
GetRegString(HKEY key, LPCTSTR value, LPTSTR data, DWORD size, LPCTSTR default_value) |
62 | 77 |
{ |
... | ... |
@@ -276,8 +276,7 @@ ReturnProcessId(HANDLE pipe, DWORD pid, DWORD count, LPHANDLE events) |
276 | 276 |
* Same format as error messages (3 line string) with error = 0 in |
277 | 277 |
* 0x%08x format, PID on line 2 and a description "Process ID" on line 3 |
278 | 278 |
*/ |
279 |
- swprintf(buf, _countof(buf), L"0x%08x\n0x%08x\n%s", 0, pid, msg); |
|
280 |
- buf[_countof(buf) - 1] = '\0'; |
|
279 |
+ openvpn_swprintf(buf, _countof(buf), L"0x%08x\n0x%08x\n%s", 0, pid, msg); |
|
281 | 280 |
|
282 | 281 |
WritePipeAsync(pipe, buf, (DWORD)(wcslen(buf) * 2), count, events); |
283 | 282 |
} |
... | ... |
@@ -402,9 +401,8 @@ ValidateOptions(HANDLE pipe, const WCHAR *workdir, const WCHAR *options) |
402 | 402 |
|
403 | 403 |
if (!CheckOption(workdir, 2, argv_tmp, &settings)) |
404 | 404 |
{ |
405 |
- swprintf(buf, _countof(buf), msg1, argv[0], workdir, |
|
406 |
- settings.ovpn_admin_group); |
|
407 |
- buf[_countof(buf) - 1] = L'\0'; |
|
405 |
+ openvpn_swprintf(buf, _countof(buf), msg1, argv[0], workdir, |
|
406 |
+ settings.ovpn_admin_group); |
|
408 | 407 |
ReturnError(pipe, ERROR_STARTUP_DATA, buf, 1, &exit_event); |
409 | 408 |
} |
410 | 409 |
goto out; |
... | ... |
@@ -421,16 +419,14 @@ ValidateOptions(HANDLE pipe, const WCHAR *workdir, const WCHAR *options) |
421 | 421 |
{ |
422 | 422 |
if (wcscmp(L"--config", argv[i]) == 0 && argc-i > 1) |
423 | 423 |
{ |
424 |
- swprintf(buf, _countof(buf), msg1, argv[i+1], workdir, |
|
425 |
- settings.ovpn_admin_group); |
|
426 |
- buf[_countof(buf) - 1] = L'\0'; |
|
424 |
+ openvpn_swprintf(buf, _countof(buf), msg1, argv[i+1], workdir, |
|
425 |
+ settings.ovpn_admin_group); |
|
427 | 426 |
ReturnError(pipe, ERROR_STARTUP_DATA, buf, 1, &exit_event); |
428 | 427 |
} |
429 | 428 |
else |
430 | 429 |
{ |
431 |
- swprintf(buf, _countof(buf), msg2, argv[i], |
|
432 |
- settings.ovpn_admin_group); |
|
433 |
- buf[_countof(buf) - 1] = L'\0'; |
|
430 |
+ openvpn_swprintf(buf, _countof(buf), msg2, argv[i], |
|
431 |
+ settings.ovpn_admin_group); |
|
434 | 432 |
ReturnError(pipe, ERROR_STARTUP_DATA, buf, 1, &exit_event); |
435 | 433 |
} |
436 | 434 |
goto out; |
... | ... |
@@ -950,8 +946,7 @@ RegisterDNS(LPVOID unused) |
950 | 950 |
|
951 | 951 |
HANDLE wait_handles[2] = {rdns_semaphore, exit_event}; |
952 | 952 |
|
953 |
- swprintf(ipcfg, _countof(ipcfg), L"%s\\%s", get_win_sys_path(), L"ipconfig.exe"); |
|
954 |
- ipcfg[_countof(ipcfg) - 1] = L'\0'; |
|
953 |
+ openvpn_swprintf(ipcfg, MAX_PATH, L"%s\\%s", get_win_sys_path(), L"ipconfig.exe"); |
|
955 | 954 |
|
956 | 955 |
if (WaitForMultipleObjects(2, wait_handles, FALSE, timeout) == WAIT_OBJECT_0) |
957 | 956 |
{ |
... | ... |
@@ -1628,9 +1623,8 @@ RunOpenvpn(LPVOID p) |
1628 | 1628 |
else if (exit_code != 0) |
1629 | 1629 |
{ |
1630 | 1630 |
WCHAR buf[256]; |
1631 |
- swprintf(buf, _countof(buf), |
|
1632 |
- L"OpenVPN exited with error: exit code = %lu", exit_code); |
|
1633 |
- buf[_countof(buf) - 1] = L'\0'; |
|
1631 |
+ openvpn_swprintf(buf, _countof(buf), |
|
1632 |
+ L"OpenVPN exited with error: exit code = %lu", exit_code); |
|
1634 | 1633 |
ReturnError(pipe, ERROR_OPENVPN_STARTUP, buf, 1, &exit_event); |
1635 | 1634 |
} |
1636 | 1635 |
Undo(&undo_lists); |
... | ... |
@@ -86,6 +86,8 @@ BOOL openvpn_vsntprintf(LPTSTR str, size_t size, LPCTSTR format, va_list arglist |
86 | 86 |
|
87 | 87 |
BOOL openvpn_sntprintf(LPTSTR str, size_t size, LPCTSTR format, ...); |
88 | 88 |
|
89 |
+BOOL openvpn_swprintf(wchar_t *const str, const size_t size, const wchar_t *const format, ...); |
|
90 |
+ |
|
89 | 91 |
DWORD GetOpenvpnSettings(settings_t *s); |
90 | 92 |
|
91 | 93 |
BOOL ReportStatusToSCMgr(SERVICE_STATUS_HANDLE service, SERVICE_STATUS *status); |
... | ... |
@@ -68,8 +68,7 @@ CheckConfigPath(const WCHAR *workdir, const WCHAR *fname, const settings_t *s) |
68 | 68 |
/* convert fname to full path */ |
69 | 69 |
if (PathIsRelativeW(fname) ) |
70 | 70 |
{ |
71 |
- swprintf(tmp, _countof(tmp), L"%s\\%s", workdir, fname); |
|
72 |
- tmp[_countof(tmp)-1] = L'\0'; |
|
71 |
+ openvpn_swprintf(tmp, _countof(tmp), L"%s\\%s", workdir, fname); |
|
73 | 72 |
config_file = tmp; |
74 | 73 |
} |
75 | 74 |
else |