From e54f6f671011f39f30b8b585979353a58e46e6aa Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jo=C3=A3o=20Abecasis?= <joao.abecasis@nokia.com>
Date: Mon, 28 Mar 2011 18:44:09 +0200
Subject: Split argument validation of _gettemp as separate function

This removes knowledge about the structure of the filename template from
the randomization process and is a pre-requisite to adding Unicode
support to the code.

Task-number: QTBUG-4796
Reviewed-by: Robin Burchell
---
 src/corelib/io/qtemporaryfile.cpp | 76 ++++++++++++++++++++++++++-------------
 1 file changed, 51 insertions(+), 25 deletions(-)

diff --git a/src/corelib/io/qtemporaryfile.cpp b/src/corelib/io/qtemporaryfile.cpp
index fe94964..f6e3426 100644
--- a/src/corelib/io/qtemporaryfile.cpp
+++ b/src/corelib/io/qtemporaryfile.cpp
@@ -95,9 +95,12 @@ QT_BEGIN_NAMESPACE
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  */
+static int createFileFromTemplate(char *const path,
+        char *const placeholderStart, char *const placeholderEnd);
+
 static int _gettemp(char *path, int slen)
 {
-    char *start, *trv, *suffp;
+    char *trv, *suffp;
 
     for (trv = path; *trv; ++trv)
         ;
@@ -109,28 +112,51 @@ static int _gettemp(char *path, int slen)
         return -1;
     }
 
+    while (trv >= path && *trv == 'X')
+        --trv;
+
+    char *const placeholderStart = trv + 1;
+    char *const placeholderEnd = suffp;
+
+    return createFileFromTemplate(path, placeholderStart, placeholderEnd);
+}
+
+/*!
+    \internal
+
+    Generates a unique file path and returns a native handle to the open file.
+    \a path is used as a template when generating unique paths,
+    \a placeholderStart and \a placeholderEnd delimit the sub-string that will
+    be randomized.
+
+    Returns an open handle to the newly created file if successful, an invalid
+    handle otherwise. In both cases, the string in \a path will be changed and
+    contain the generated path name.
+*/
+static int createFileFromTemplate(char *const path,
+        char *const placeholderStart, char *const placeholderEnd)
+{
+    Q_ASSERT(placeholderEnd > placeholderStart);
+
     // Initialize placeholder with random chars + PID.
     {
+        char *rIter = placeholderEnd;
+
 #if defined(QT_BUILD_CORE_LIB)
         qint64 pid = QCoreApplication::applicationPid();
-        while (trv >= path && *trv == 'X' && pid != 0) {
-            *trv-- = (pid % 10) + '0';
+        do {
+            *--rIter = (pid % 10) + '0';
             pid /= 10;
-        }
+        } while (rIter != placeholderStart && pid != 0);
 #endif
 
-        while (trv >= path && *trv == 'X') {
-            char c;
-
-            // CHANGE arc4random() -> random()
-            int pid = (qrand() & 0xffff) % (26+26);
-            if (pid < 26)
-                c = pid + 'A';
+        while (rIter != placeholderStart) {
+            char ch = char((qrand() & 0xffff) % (26 + 26));
+            if (ch < 26)
+                *--rIter = ch + 'A';
             else
-                c = (pid - 26) + 'a';
-            *trv-- = c;
+                *--rIter = ch - 26 + 'a';
         }
-        start = trv + 1;
     }
 
     for (;;) {
@@ -149,24 +175,24 @@ static int _gettemp(char *path, int slen)
 #endif
 
         /* tricky little algorwwithm for backward compatibility */
-        for (trv = start;;) {
+        for (char *iter = placeholderStart;;) {
             // Character progression: [0-9] => 'a' ... 'z' => 'A' .. 'Z'
             // String progression: "ZZaiC" => "aabiC"
-            if (!*trv)
+            if (!*iter)
                 return -1;
-            if (*trv == 'Z') {
-                if (trv == suffp)
+            if (*iter == 'Z') {
+                if (iter == placeholderEnd)
                     return -1;
-                *trv++ = 'a';
+                *iter++ = 'a';
             } else {
-                if (isdigit(*trv))
-                    *trv = 'a';
-                else if (*trv == 'z') /* inc from z to A */
-                    *trv = 'A';
+                if (isdigit(*iter))
+                    *iter = 'a';
+                else if (*iter == 'z') /* inc from z to A */
+                    *iter = 'A';
                 else {
-                    if (trv == suffp)
+                    if (iter == placeholderEnd)
                         return -1;
-                    ++*trv;
+                    ++*iter;
                 }
                 break;
             }
-- 
cgit v0.12