From bc07627ecf743de52900fb82e6779eb625a37627 Mon Sep 17 00:00:00 2001
From: Valery Kharseko <vharseko@3a-systems.ru>
Date: Fri, 24 Jul 2026 13:47:53 +0000
Subject: [PATCH] Fix all cpp/ CodeQL code-scanning alerts in Windows build-tools (#757)

---
 opendj-server-legacy/src/build-tools/windows/winlauncher.c |   18 ++-
 opendj-server-legacy/src/build-tools/windows/common.h      |   10 +
 opendj-server-legacy/src/build-tools/windows/service.c     |  215 +++++++++++++++++++----------------
 opendj-server-legacy/src/build-tools/windows/service.h     |    5 
 opendj-server-legacy/src/build-tools/windows/common.c      |   67 +++++++---
 5 files changed, 187 insertions(+), 128 deletions(-)

diff --git a/opendj-server-legacy/src/build-tools/windows/common.c b/opendj-server-legacy/src/build-tools/windows/common.c
index 2221221..bd62f08 100644
--- a/opendj-server-legacy/src/build-tools/windows/common.c
+++ b/opendj-server-legacy/src/build-tools/windows/common.c
@@ -13,10 +13,12 @@
  *
  * Copyright 2008-2010 Sun Microsystems, Inc.
  * Portions Copyright 2013 ForgeRock AS.
+ * Portions Copyright 2026 3A Systems, LLC.
  */
 
 #include "common.h"
 #include "service.h"
+#include <direct.h>
 #include <errno.h>
 #include <fcntl.h>
 #include <io.h>
@@ -112,7 +114,7 @@
     debug("createBatchFileChildProcess: the batch file path is too long.");
 	return FALSE;
   }
-  sprintf(command, "/c %s", batchFile);
+  _snprintf(command, COMMAND_SIZE, "/c %s", batchFile);
   debug("createBatchFileChildProcess: Attempting to create child process '%s' background=%d.",
 	  command,
       background);
@@ -259,7 +261,7 @@
   char * logFile;
   FILE *fp;
 	time_t rawtime;
-  struct tm * timeinfo;
+  struct tm timeinfo;
   char formattedTime[100];
   
   if (noMessageLogged)
@@ -272,8 +274,8 @@
 
   // Time-stamp
   time(&rawtime);
-  timeinfo = localtime(&rawtime);
-  strftime(formattedTime, 100, "%Y/%m/%d %H:%M:%S", timeinfo);
+  localtime_s(&timeinfo, &rawtime);
+  strftime(formattedTime, 100, "%Y/%m/%d %H:%M:%S", &timeinfo);
   
   logFile = getDebugLogFileName();
   deleteIfLargerThan(logFile, MAX_DEBUG_LOG_SIZE);
@@ -310,16 +312,13 @@
   char execName [MAX_PATH];
   char * lastSlash;
   char logpath[MAX_PATH];
-  char * temp;  
-  FILE *file; 
 
-  if (logFile != NULL) 
+  if (logFile != NULL)
   {
     return logFile;
   }
-  temp = getenv("TEMP");
-  
-  // Get the name of the executable.  
+
+  // Get the name of the executable.
   GetModuleFileName (
     NULL,
     execName,
@@ -339,18 +338,36 @@
   strcpy(logpath, execName); 
   strcat(logpath, "\\logs\\"); 
   
-  // If the log folder doesn's exist in the instance path
+  // If the log folder doesn't exist in the instance path
   // we create the log file in the temp directory.
-  if (isExistingDirectory(logpath)) 
+  if (isExistingDirectory(logpath))
   {
-    sprintf(path, "%s\\logs\\%s", execName, DEBUG_LOG_NAME);
-  } else {
-    strcat(temp, "\\logs\\");
-    mkdir(temp);
-    strcat(temp, DEBUG_LOG_NAME);
-    file = fopen(temp,"a+");
-    fclose(file);
-    sprintf(path, "%s", temp);
+    _snprintf(path, MAX_PATH, "%s\\logs\\%s", execName, DEBUG_LOG_NAME);
+    path[MAX_PATH - 1] = '\0';
+  }
+  else
+  {
+    // Fall back to the OS temp directory.  Use GetTempPath (a trusted OS API
+    // that resolves the TMP/TEMP/USERPROFILE locations) rather than
+    // getenv("TEMP"), whose buffer must not be extended in place.
+    char tempDir[MAX_PATH];
+    DWORD tempLen = GetTempPath(MAX_PATH, tempDir);
+    if ((tempLen > 0) && (tempLen < MAX_PATH))
+    {
+      // GetTempPath returns a path that already ends with a backslash.
+      char tempLogDir[MAX_PATH];
+      _snprintf(tempLogDir, MAX_PATH, "%slogs\\", tempDir);
+      tempLogDir[MAX_PATH - 1] = '\0';
+      _mkdir(tempLogDir);
+      _snprintf(path, MAX_PATH, "%s%s", tempLogDir, DEBUG_LOG_NAME);
+      path[MAX_PATH - 1] = '\0';
+    }
+    else
+    {
+      // Could not determine a temp directory: fall back to the log file name.
+      _snprintf(path, MAX_PATH, "%s", DEBUG_LOG_NAME);
+      path[MAX_PATH - 1] = '\0';
+    }
   }
 
   logFile = _strdup(path);
@@ -415,6 +432,14 @@
 {
   DWORD str = GetFileAttributes(fileName);
 
-  return (str != INVALID_FILE_ATTRIBUTES && 
+  return (str != INVALID_FILE_ATTRIBUTES &&
          (str & FILE_ATTRIBUTE_DIRECTORY));
 }
+
+// ---------------------------------------------------------------
+// See common.h for the contract of this function.
+// ---------------------------------------------------------------
+BOOL isSafePath(const char* path)
+{
+  return (path != NULL) && (strstr(path, "..") == NULL);
+}
diff --git a/opendj-server-legacy/src/build-tools/windows/common.h b/opendj-server-legacy/src/build-tools/windows/common.h
index d666576..405e405 100644
--- a/opendj-server-legacy/src/build-tools/windows/common.h
+++ b/opendj-server-legacy/src/build-tools/windows/common.h
@@ -12,8 +12,12 @@
  * information: "Portions Copyright [year] [name of copyright owner]".
  *
  * Copyright 2008-2010 Sun Microsystems, Inc.
+ * Portions Copyright 2026 3A Systems, LLC.
  */
 
+#ifndef OPENDJ_WINDOWS_COMMON_H
+#define OPENDJ_WINDOWS_COMMON_H
+
 // Just some functions and constants to be used by winlauncher.c
 // and service.c
 
@@ -32,3 +36,9 @@
 void updateDebugFlag(char* argv[], int argc);
 BOOL waitForProcess(PROCESS_INFORMATION* procInfo, DWORD waitTime,
   DWORD* exitCode);
+
+// Returns TRUE if the given path is non-NULL and does not contain a
+// parent-directory reference ("..") that could be used for path traversal.
+BOOL isSafePath(const char* path);
+
+#endif // OPENDJ_WINDOWS_COMMON_H
diff --git a/opendj-server-legacy/src/build-tools/windows/service.c b/opendj-server-legacy/src/build-tools/windows/service.c
index 1fd7e37..587cc32 100644
--- a/opendj-server-legacy/src/build-tools/windows/service.c
+++ b/opendj-server-legacy/src/build-tools/windows/service.c
@@ -190,7 +190,7 @@
 
   // Check whether the Registry Key is already created,
   // If so don't create a new one.
-  sprintf (subkey, EVENT_LOG_KEY, serviceName);
+  _snprintf (subkey, MAX_REGISTRY_KEY, EVENT_LOG_KEY, serviceName);
   result = RegOpenKeyEx(
   HKEY_LOCAL_MACHINE,
   subkey,
@@ -292,7 +292,7 @@
   // Set the number of categories: 1 (OPENDJ)
   if (success)
   {
-    long result = RegSetValueEx(
+    result = RegSetValueEx(
     hkey,                    // subkey handle
     "CategoryCount",         // value name
     0,                       // must be zero
@@ -346,7 +346,7 @@
 
   // Check whether the Registry Key is already created,
   // If so don't create a new one.
-  sprintf (subkey, EVENT_LOG_KEY, serviceName);
+  _snprintf (subkey, MAX_REGISTRY_KEY, EVENT_LOG_KEY, serviceName);
   result = RegOpenKeyEx(
   HKEY_LOCAL_MACHINE,
   subkey,
@@ -390,7 +390,10 @@
   char subkey [MAX_SERVICE_NAME];
   debug("Registering the Event Log for service '%s'.", serviceName);
 
-  sprintf (subkey, serviceName);
+  // _snprintf does not null-terminate on truncation (MSVC), so terminate
+  // explicitly: serviceName ultimately derives from argv and is unbounded.
+  _snprintf (subkey, MAX_SERVICE_NAME, "%s", serviceName);
+  subkey[MAX_SERVICE_NAME - 1] = '\0';
 
   eventLog = RegisterEventSource(
   NULL,      // local host
@@ -427,11 +430,11 @@
   {
     debug("Determining if the server is running.");
   }
-  if (strlen(relativePath)+strlen(_instanceDir)+1 < MAX_PATH)
+  if (isSafePath(_instanceDir) && strlen(relativePath)+strlen(_instanceDir)+1 < MAX_PATH)
   {
     int fd;
 
-    sprintf(lockFile, "%s%s", _instanceDir, relativePath);
+    _snprintf(lockFile, MAX_PATH, "%s%s", _instanceDir, relativePath);
     if (mustDebug)
     {
       debug(
@@ -517,7 +520,7 @@
 
   if (strlen(relativePath)+strlen(_instanceDir)+1 < COMMAND_SIZE)
   {
-  sprintf(command, "\"%s%s\" --windowsNetStart", _instanceDir, relativePath);
+  _snprintf(command, COMMAND_SIZE, "\"%s%s\" --windowsNetStart", _instanceDir, relativePath);
     debug("doStartApplication: Launching batch file: %s", command);
     createOk = createBatchFileChildProcess(command, FALSE, &procInfo);
 
@@ -709,7 +712,7 @@
   debug("doStopApplication");
   if (strlen(relativePath)+strlen(_instanceDir)+1 < COMMAND_SIZE)
   {
-    sprintf(command, "\"%s%s\" --windowsNetStop", _instanceDir, relativePath);
+    _snprintf(command, COMMAND_SIZE, "\"%s%s\" --windowsNetStop", _instanceDir, relativePath);
 
     // launch the command
     if (spawn(command, FALSE) != -1)
@@ -808,7 +811,7 @@
       if ((strlen(fileName) + strlen(" start ") + strlen(_instanceDir) +
           2 * strlen("\"\"")) < COMMAND_SIZE)
       {
-        sprintf(serviceBinPath, "\"%s\" start \"%s\"", fileName,
+        _snprintf(serviceBinPath, COMMAND_SIZE, "\"%s\" start \"%s\"", fileName,
         _instanceDir);
       }
       else
@@ -873,7 +876,7 @@
               // This function assumes that there are at least
               // MAX_SERVICE_NAME (256) characters reserved in
               // servicename.
-              sprintf(serviceName, curService.serviceName);
+              _snprintf(serviceName, MAX_SERVICE_NAME, "%s", curService.serviceName);
               returnValue = SERVICE_RETURN_OK;
             }
             else
@@ -1061,11 +1064,11 @@
   ServiceReturnCode code;
   // a checkpoint value indicate the progress of an operation
   DWORD checkPoint = CHECKPOINT_FIRST_VALUE;
-  SERVICE_STATUS_HANDLE serviceStatusHandle;
+  // static so its address does not escape the stack when stored in the
+  // global _serviceStatusHandle; there is only one service per process.
+  static SERVICE_STATUS_HANDLE serviceStatusHandle;
   BOOL running;
 
-  // __debugbreak();
-
   debug("serviceMain");
 
   code = createServiceBinPath(cmdToRun);
@@ -1133,16 +1136,12 @@
   if (!running && code == SERVICE_RETURN_OK)
   {
     WORD argCount = 1;
-    const char *argc[] = {_instanceDir};
+    const char *logArgs[] = {_instanceDir};
     code = doStartApplication(_serviceStatusHandle, &checkPoint);
 
-    switch (code)
+    if (code != SERVICE_RETURN_OK)
     {
-      case SERVICE_RETURN_OK:
-      // start is ok: do nothing for the moment.
-      break;
-
-      default:
+      // start failed
       debugError("serviceMain: doStartApplication() failed");
       code = SERVICE_RETURN_ERROR;
       _serviceCurStatus = SERVICE_STOPPED;
@@ -1156,7 +1155,7 @@
       reportLogEvent(
         EVENTLOG_ERROR_TYPE,
         WIN_EVENT_ID_SERVER_START_FAILED,
-        argCount, argc
+        argCount, logArgs
       );
     }
   }
@@ -1222,7 +1221,7 @@
       if (!updatedRunningStatus)
       {
         WORD argCount = 1;
-            const char *argc[] = {_instanceDir};
+            const char *logArgs[] = {_instanceDir};
             updateServiceStatus (
                _serviceCurStatus,
                NO_ERROR,
@@ -1234,7 +1233,7 @@
              reportLogEvent(
                EVENTLOG_SUCCESS,
                WIN_EVENT_ID_SERVER_STARTED,
-               argCount, argc
+               argCount, logArgs
              );
        updatedRunningStatus = TRUE;
       }
@@ -1269,7 +1268,7 @@
                   (state == SERVICE_STOP_PENDING))))
             {
               WORD argCount = 1;
-              const char *argc[] = {_instanceDir};
+              const char *logArgs[] = {_instanceDir};
               _serviceCurStatus = SERVICE_STOPPED;
               debug("checking in serviceMain serviceHandler: service stopped with error.");
 
@@ -1283,7 +1282,7 @@
               reportLogEvent(
                 EVENTLOG_ERROR_TYPE,
                 WIN_EVENT_ID_SERVER_STOPPED_OUTSIDE_SCM,
-                argCount, argc);
+                argCount, logArgs);
             }
             break;
           }
@@ -1324,6 +1323,68 @@
 }  // doTerminateService
 
 // ----------------------------------------------------
+// Stops the service from within the service handler.  Shared by the
+// SERVICE_CONTROL_STOP and SERVICE_CONTROL_SHUTDOWN control codes.
+// ----------------------------------------------------
+static void stopServiceFromHandler(void)
+{
+  ServiceReturnCode code;
+  DWORD checkpoint;
+
+  // update service status to STOP_PENDING
+  debug("serviceHandler: stop");
+  _serviceCurStatus = SERVICE_STOP_PENDING;
+  checkpoint = CHECKPOINT_FIRST_VALUE;
+  updateServiceStatus (
+  _serviceCurStatus,
+  NO_ERROR,
+  0,
+  checkpoint++,
+  TIMEOUT_STOP_SERVICE,
+  _serviceStatusHandle
+  );
+
+  // let's try to stop the application whatever may be the status above
+  // (best effort mode)
+  code = doStopApplication();
+  if (code == SERVICE_RETURN_OK)
+  {
+    WORD argCount = 1;
+    const char *logArgs[] = {_instanceDir};
+    _serviceCurStatus = SERVICE_STOPPED;
+    updateServiceStatus (
+    _serviceCurStatus,
+    NO_ERROR,
+    0,
+    CHECKPOINT_NO_ONGOING_OPERATION,
+    TIMEOUT_NONE,
+    _serviceStatusHandle
+    );
+
+    // again, let's ignore the above status and
+    // notify serviceMain that service has stopped
+    doTerminateService (_terminationEvent);
+    reportLogEvent(
+    EVENTLOG_SUCCESS,
+    WIN_EVENT_ID_SERVER_STOP,
+    argCount, logArgs
+    );
+  }
+  else
+  {
+    WORD argCount = 1;
+    const char *logArgs[] = {_instanceDir};
+    debug("serviceHandler: The server could not be stopped.");
+    // We could not stop the server
+    reportLogEvent(
+    EVENTLOG_ERROR_TYPE,
+    WIN_EVENT_ID_SERVER_STOP_FAILED,
+    argCount, logArgs
+    );
+  }
+}  // stopServiceFromHandler
+
+// ----------------------------------------------------
 // This function is the handler of the service. It is processing the
 // commands send by the SCM. Commands can be: STOP, PAUSE, CONTINUE,
 // SHUTDOWN and INTERROGATE.
@@ -1333,7 +1394,6 @@
 void serviceHandler(DWORD controlCode)
 {
   ServiceReturnCode code;
-  DWORD checkpoint;
   BOOL running;
   debug("serviceHandler called with controlCode=%d.", controlCode);
   switch (controlCode)
@@ -1343,60 +1403,9 @@
     // -> no break here
       debug("serviceHandler: shutdown");
     case SERVICE_CONTROL_STOP:
-    {
-      // update service status to STOP_PENDING
-      debug("serviceHandler: stop");
-      _serviceCurStatus = SERVICE_STOP_PENDING;
-      checkpoint = CHECKPOINT_FIRST_VALUE;
-      updateServiceStatus (
-      _serviceCurStatus,
-      NO_ERROR,
-      0,
-      checkpoint++,
-      TIMEOUT_STOP_SERVICE,
-      _serviceStatusHandle
-      );
-
-      // let's try to stop the application whatever may be the status above
-      // (best effort mode)
-      code = doStopApplication();
-      if (code == SERVICE_RETURN_OK)
-      {
-        WORD argCount = 1;
-        const char *argc[] = {_instanceDir};
-        _serviceCurStatus = SERVICE_STOPPED;
-        updateServiceStatus (
-        _serviceCurStatus,
-        NO_ERROR,
-        0,
-        CHECKPOINT_NO_ONGOING_OPERATION,
-        TIMEOUT_NONE,
-        _serviceStatusHandle
-        );
-
-        // again, let's ignore the above status and
-        // notify serviceMain that service has stopped
-        doTerminateService (_terminationEvent);
-        reportLogEvent(
-        EVENTLOG_SUCCESS,
-        WIN_EVENT_ID_SERVER_STOP,
-        argCount, argc
-        );
-      }
-      else
-      {
-        WORD argCount = 1;
-        const char *argc[] = {_instanceDir};
-    debug("serviceHandler: The server could not be stopped.");
-        // We could not stop the server
-        reportLogEvent(
-        EVENTLOG_ERROR_TYPE,
-        WIN_EVENT_ID_SERVER_STOP_FAILED,
-        argCount, argc
-        );
-      }
+      // update service status to STOP_PENDING and stop the application
+      stopServiceFromHandler();
       break;
-    }
 
 
     // Request to pause the service
@@ -1526,7 +1535,7 @@
       {
         if (strlen(serviceConfig->lpBinaryPathName) < COMMAND_SIZE)
         {
-          sprintf(binPathName, serviceConfig->lpBinaryPathName);
+          _snprintf(binPathName, COMMAND_SIZE, "%s", serviceConfig->lpBinaryPathName);
           returnValue = SERVICE_RETURN_OK;
         }
         else
@@ -1543,11 +1552,8 @@
     }
   }
 
-  // free buffers
-  if (serviceConfig != NULL)
-  {
-    free(serviceConfig);
-  }
+  // free buffers (free(NULL) is a safe no-op, so no guard is needed)
+  free(serviceConfig);
 
   return returnValue;
 } // getBinaryPathName
@@ -1618,12 +1624,12 @@
 
         if (! svcStatusOk)
         {
-          DWORD lastError = GetLastError();
-          if (lastError != ERROR_MORE_DATA)
+          DWORD innerLastError = GetLastError();
+          if (innerLastError != ERROR_MORE_DATA)
           {
             returnValue = SERVICE_RETURN_ERROR;
             debug("getServiceList: second try generic error. Code [%d]",
-                lastError);
+                innerLastError);
           }
           else
           {
@@ -1690,8 +1696,10 @@
   if (scm != NULL)
   {
     CloseServiceHandle (scm);
-    // free the result buffer
-    if (lpServiceData != NULL)
+    // free the result buffer, but only if it was heap-allocated: it still
+    // points to the stack-based serviceData when the first EnumServicesStatus
+    // call succeeded without needing a larger buffer.
+    if (lpServiceData != &serviceData)
     {
       free (lpServiceData);
     }
@@ -1780,12 +1788,15 @@
   {
     if (i == 1)
     {
-      sprintf(serviceName, baseName);
+      _snprintf(serviceName, MAX_SERVICE_NAME, "%s", baseName);
     }
     else
     {
-      sprintf(serviceName, "%s-%d", baseName, i);
+      _snprintf(serviceName, MAX_SERVICE_NAME, "%s-%d", baseName, i);
     }
+    // _snprintf does not null-terminate on truncation (MSVC), and baseName
+    // (== argv[3]) is unbounded, so terminate explicitly.
+    serviceName[MAX_SERVICE_NAME - 1] = '\0';
 
     nameInUseResult = serviceNameInUse(serviceName);
 
@@ -1930,11 +1941,8 @@
     CloseServiceHandle (scm);
   }
 
-  // free names
-  if (serviceName != NULL)
-  {
-    free (serviceName);
-  }
+  // free names (free(NULL) is a safe no-op, so no guard is needed)
+  free (serviceName);
 
   debug("createServiceInScm returning %d.", returnValue);
 
@@ -1970,7 +1978,7 @@
     serviceName,
     SERVICE_ALL_ACCESS | DELETE
     );
-    debug("After opening service myService=%d.", myService);
+    debug("After opening service myService=%p.", (void*)myService);
     if (myService == NULL)
     {
       debugError("Failed to open the service '%s'. Last error = %d",
@@ -2176,7 +2184,7 @@
     {
       // There is a valid serviceName for the command to run, so
       // OpenDJ is registered as a service.
-      fprintf(stdout, serviceName);
+      fprintf(stdout, "%s", serviceName);
       returnCode = 0;
       debug("Service '%s' is enabled.", serviceName);
     }
@@ -2375,6 +2383,13 @@
 
 
 
+// ---------------------------------------------------------------
+// Entry point for the opendj_service executable.  Dispatches to the
+// requested subcommand (create, state, remove, start, isrunning or
+// cleanup); each operates on the OpenDJ instance directory (or the
+// service name, for cleanup) given as the following argument.
+// Returns 0 on success and a non-zero value otherwise.
+// ---------------------------------------------------------------
 int main(int argc, char* argv[])
 {
   char* subcommand;
@@ -2388,8 +2403,6 @@
       debug("  argv[%d] = '%s'", i, argv[i]);
   }
 
-  // __debugbreak();
-
   if (argc <= 1)
   {
     fprintf(stdout,
diff --git a/opendj-server-legacy/src/build-tools/windows/service.h b/opendj-server-legacy/src/build-tools/windows/service.h
index d75deba..96ad255 100644
--- a/opendj-server-legacy/src/build-tools/windows/service.h
+++ b/opendj-server-legacy/src/build-tools/windows/service.h
@@ -16,6 +16,9 @@
  * Portions Copyright 2026 3A Systems, LLC.
  */
 
+#ifndef OPENDJ_WINDOWS_SERVICE_H
+#define OPENDJ_WINDOWS_SERVICE_H
+
 #include "common.h"
 #include <errno.h>
 #include <fcntl.h>
@@ -100,3 +103,5 @@
 void serviceHandler(DWORD controlCode);
 BOOL getServiceStatus(char *serviceName, LPDWORD returnState);
 
+#endif // OPENDJ_WINDOWS_SERVICE_H
+
diff --git a/opendj-server-legacy/src/build-tools/windows/winlauncher.c b/opendj-server-legacy/src/build-tools/windows/winlauncher.c
index 2e5d851..e449a13 100644
--- a/opendj-server-legacy/src/build-tools/windows/winlauncher.c
+++ b/opendj-server-legacy/src/build-tools/windows/winlauncher.c
@@ -12,6 +12,7 @@
  * information: "Portions Copyright [year] [name of copyright owner]".
  *
  *      Copyright 2008 Sun Microsystems, Inc.
+ * Portions Copyright 2026 3A Systems, LLC.
  */
 
 #include "winlauncher.h"
@@ -29,9 +30,14 @@
 
   debug("Attempting to get the PID file for instanceDir='%s'", instanceDir);
 
-  if ((strlen(relativePath) + strlen(instanceDir)) < maxSize)
+  if (!isSafePath(instanceDir))
   {
-    sprintf(pidFile, "%s\\logs\\server.pid", instanceDir);
+    debugError("Unable to get the PID file name because the instance dir is not a safe path.");
+    returnValue = FALSE;
+  }
+  else if ((strlen(relativePath) + strlen(instanceDir)) < maxSize)
+  {
+    _snprintf(pidFile, maxSize, "%s\\logs\\server.pid", instanceDir);
     returnValue = TRUE;
     debug("PID file name is '%s'.", pidFile);
   }
@@ -283,7 +289,7 @@
     {
       if (curCmdInd + strlen(" ") < maxSize)
       {
-        sprintf (&command[curCmdInd], " ");
+        _snprintf (&command[curCmdInd], maxSize - curCmdInd, " ");
         curCmdInd = strlen(command);
       }
       else
@@ -314,7 +320,7 @@
         if (curCmdInd + strlen("\"\"") + strlen(curarg) < maxSize)
         {
           // no begining quote and white space inside => add quotes
-          sprintf (&command[curCmdInd], "\"%s\"", curarg);
+          _snprintf (&command[curCmdInd], maxSize - curCmdInd, "\"%s\"", curarg);
           curCmdInd = strlen (command);
         }
         else
@@ -327,7 +333,7 @@
         if (curCmdInd + strlen(curarg) < maxSize)
         {
           // no white space or quotes detected, keep the arg as is
-          sprintf (&command[curCmdInd], "%s", curarg);
+          _snprintf (&command[curCmdInd], maxSize - curCmdInd, "%s", curarg);
           curCmdInd = strlen (command);
         }
         else
@@ -339,7 +345,7 @@
     } else {
       if (curCmdInd + strlen("\"\"") < maxSize)
       {
-        sprintf (&command[curCmdInd], "\"\"");
+        _snprintf (&command[curCmdInd], maxSize - curCmdInd, "\"\"");
         curCmdInd = strlen (command);
       }
       else

--
Gitblit v1.10.0