Browse code

Introduce openvpn_swprintf() with nul termination guarantee

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>

Lev Stipakov authored on 2018/10/22 19:19:31
Showing 7 changed files
... ...
@@ -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