Bug 791742: Consider driver version substrings in decimals. r=joedrew
authorBas Schouten <bschouten@mozilla.com>
Mon, 17 Sep 2012 20:50:38 +0000
changeset 107289 b898c97f998d5360db69ae767e23ce40201aad41
parent 107288 89085b91ea2cea14a34e3618bf4c802bec86115e
child 107290 703fb179c834b67cb55953d10dc44a693a52cbb4
push id23480
push usergraememcc_firefox@graeme-online.co.uk
push dateTue, 18 Sep 2012 11:48:11 +0000
treeherdermozilla-central@e4757379b99a [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjoedrew
bugs791742
milestone18.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 791742: Consider driver version substrings in decimals. r=joedrew
widget/xpwidgets/GfxDriverInfo.h
--- a/widget/xpwidgets/GfxDriverInfo.h
+++ b/widget/xpwidgets/GfxDriverInfo.h
@@ -119,25 +119,92 @@ struct GfxDriverInfo
 
   static const nsAString& GetDeviceVendor(DeviceVendor id);
   static nsAString* mDeviceVendors[DeviceVendorMax];
 };
 
 #define GFX_DRIVER_VERSION(a,b,c,d) \
   ((uint64_t(a)<<48) | (uint64_t(b)<<32) | (uint64_t(c)<<16) | uint64_t(d))
 
+// All destination string storage needs to have at least 5 bytes available.
+static bool SplitDriverVersion(const char *aSource, char *aAStr, char *aBStr, char *aCStr, char *aDStr)
+{
+  // sscanf doesn't do what we want here to we parse this manually.
+  int len = strlen(aSource);
+  char *dest[4] = { aAStr, aBStr, aCStr, aDStr };
+  int destIdx = 0;
+  int destPos = 0;
+
+  for (int i = 0; i < len; i++) {
+    if (destIdx > ArrayLength(dest)) {
+      // Invalid format found. Ensure we don't access dest beyond bounds.
+      return false;
+    }
+
+    if (aSource[i] == '.') {
+      dest[destIdx++][destPos] = 0;
+      destPos = 0;
+      continue;
+    }
+
+    if (destPos > 3) {
+      // Ignore more than 4 chars. Ensure we never access dest[destIdx]
+      // beyond its bounds.
+      continue;
+    }
+
+    dest[destIdx][destPos++] = aSource[i];
+  }
+
+  // Add last terminator.
+  dest[destIdx][destPos] = 0;
+
+  if (destIdx != ArrayLength(dest) - 1) {
+    return false;
+  }
+  return true;
+}
+
+// This allows us to pad driver versiopn 'substrings' with 0s, this
+// effectively allows us to treat the version numbers as 'decimals'. This is
+// a little strange but this method seems to do the right thing for all
+// different vendor's driver strings. i.e. .98 will become 9800, which is
+// larger than .978 which would become 9780.
+static void PadDriverDecimal(char *aString)
+{
+  for (int i = 0; i < 4; i++) {
+    if (!aString[i]) {
+      for (int c = i; c < 4; c++) {
+        aString[c] = '0';
+      }
+      break;
+    }
+  }
+  aString[4] = 0;
+}
+
 inline bool
 ParseDriverVersion(nsAString& aVersion, uint64_t *aNumericVersion)
 {
 #if defined(XP_WIN)
   int a, b, c, d;
+  char aStr[8], bStr[8], cStr[8], dStr[8];
   /* honestly, why do I even bother */
-  if (sscanf(NS_LossyConvertUTF16toASCII(aVersion).get(),
-             "%d.%d.%d.%d", &a, &b, &c, &d) != 4)
+  if (!SplitDriverVersion(NS_LossyConvertUTF16toASCII(aVersion).get(), aStr, bStr, cStr, dStr))
     return false;
+
+  PadDriverDecimal(bStr);
+  PadDriverDecimal(cStr);
+  PadDriverDecimal(dStr);
+
+  a = atoi(aStr);
+  b = atoi(bStr);
+  c = atoi(cStr);
+  d = atoi(dStr);
+
   if (a < 0 || a > 0xffff) return false;
   if (b < 0 || b > 0xffff) return false;
   if (c < 0 || c > 0xffff) return false;
   if (d < 0 || d > 0xffff) return false;
 
   *aNumericVersion = GFX_DRIVER_VERSION(a, b, c, d);
 #elif defined(ANDROID)
   // Can't use aVersion.ToInteger() because that's not compiled into our code