View Issue Details

IDProjectCategoryView StatusLast Update
0006519JEDI Code LibraryJclSysInfopublic2016-08-03 16:46
Reporterintersat2_gmail_comAssigned ToAHUser 
PrioritynormalSeveritycrashReproducibilityalways
Status resolvedResolutionfixed 
Product VersionVersion 2.5 (Subversion repository/Daily zips) 
Target VersionFixed in Version 
Summary0006519: GetWindowsMajorVersionNumber strToInt(StrBefore('.' Crash on Windows Storage Server 2012 R2 in JclSysInfo.pas > initialization s
DescriptionOS:Windows Storage Server 2012 R2
HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\Windows NT\CurrentVersion\CurrentVersion = 6.3
HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\Windows NT\CurrentVersion\ProductName = 'Windows Storage Server 2012 R2 Standard'

The crash is generated because 'ProductName' <> 'Windows Server 2012 R2'
GetWindowsMajorVersionNumber calls StrBefore which calls StrFind which calls StrIPos which calls StrUpper which calls StrUpperInPlace which calls StrCase(S, StrUpOffset) which needs StrCaseMap to be populated.

But since this all is run as part of the initialization section of JclSysInfo, StrCaseMap is not populated yet.

Therefore StrUpper returns #0#0#0, StrBefore returns '', StrToInt crashes the process.
TagsNo tags attached.
Fixed in GIT commit
Fixed in SVN revision
IDE versionAll

Relationships

duplicate of 0006489 resolvedAHUser Indirect call to uninitialized JclStrings.StrCaseMap variable from JclSysInfo module. 

Activities

2016-08-03 02:48

 

intersat2_gmail_com

2016-08-03 14:58

reporter   ~0021314

Last edited: 2016-08-03 15:00

From a27f0e7d00351135282264f7e49a8c761b0ceb60 Mon Sep 17 00:00:00 2001
From: Bogdan B
Date: Wed, 3 Aug 2016 14:37:50 +0300
Subject: [PATCH 1/1] JEDI JCL
 http://issuetracker.delphi-jedi.org/view.php?id=6519 Summary 0006519:
 GetWindowsMajorVersionNumber strToInt(StrBefore('.' Crash on Windows Storage
 Server 2012 R2 in JclSysInfo.pas > initialization s Description OS:Windows
 Storage Server 2012 R2
 HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\Windows
 NT\CurrentVersion\CurrentVersion = 6.3
 HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\Windows
 NT\CurrentVersion\ProductName = 'Windows Storage Server 2012 R2 Standard' The
 crash is generated because 'ProductName' <> 'Windows Server 2012 R2'
 GetWindowsMajorVersionNumber calls StrBefore which calls StrFind which calls
 StrIPos which calls StrUpper which calls StrUpperInPlace which calls
 StrCase(S, StrUpOffset) which needs StrCaseMap to be populated. But since
 this all is run as part of the initialization section of JclSysInfo,
 StrCaseMap is not populated yet. Therefore StrUpper returns #0#0#0, StrBefore
 returns '', StrToInt crashes the process.

---
 ThirdParty/JEDI/jcl/common/JclSysInfo.pas | 26 ++++++++++++++++++++++++--
 1 file changed, 24 insertions(+), 2 deletions(-)

diff --git a/ThirdParty/JEDI/jcl/common/JclSysInfo.pas b/ThirdParty/JEDI/jcl/common/JclSysInfo.pas
index 7e4c814..efd4045 100644
--- a/ThirdParty/JEDI/jcl/common/JclSysInfo.pas
+++ b/ThirdParty/JEDI/jcl/common/JclSysInfo.pas
@@ -3874,6 +3874,28 @@ begin
     Result := Win32BuildNumber;
 end;
 
+function StrBeforeCaseSensitive(const SubStr, S: string): string;
+var
+ P: SizeInt;
+begin
+ P := Pos(SubStr, S, 1); //StrFind(SubStr, S, 1);
+ if P <= 0 then
+ Result := S
+ else
+ Result := StrLeft(S, P - 1);
+end;
+
+function StrAfterCaseSensitive(const SubStr, S: string): string;
+var
+ P: SizeInt;
+begin
+ P := Pos(SubStr, S, 1); //StrFind(SubStr, S, 1); // StrFind is case-insensitive pos
+ if P <= 0 then
+ Result := '' // substr not found -> nothing after it
+ else
+ Result := StrRestOf(S, P + Length(SubStr));
+end;
+
 function GetWindowsMajorVersionNumber: Integer;
 begin
   // Starting with Windows 8.1, the GetVersion(Ex) API is deprecated and will detect the
@@ -3885,7 +3907,7 @@ begin
     // If CurrentMajorVersionNumber not present in registry then use CurrentVersion
     Result := RegReadIntegerDef(HKEY_LOCAL_MACHINE, 'SOFTWARE\Microsoft\Windows NT\CurrentVersion', 'CurrentMajorVersionNumber', -1);
     if Result = -1 then
- Result := strToInt(StrBefore('.', RegReadStringDef(HKEY_LOCAL_MACHINE, 'SOFTWARE\Microsoft\Windows NT\CurrentVersion', 'CurrentVersion', intToStr(Win32MajorVersion) + '.' + intToStr(Win32MinorVersion))));
+ Result := StrToInt(StrBeforeCaseSensitive('.', RegReadStringDef(HKEY_LOCAL_MACHINE, 'SOFTWARE\Microsoft\Windows NT\CurrentVersion', 'CurrentVersion', intToStr(Win32MajorVersion) + '.' + intToStr(Win32MinorVersion))));
   end
   else
     Result := Win32MajorVersion;
@@ -3902,7 +3924,7 @@ begin
     // If CurrentMinorVersionNumber not present then use CurrentVersion
     Result := RegReadIntegerDef(HKEY_LOCAL_MACHINE, 'SOFTWARE\Microsoft\Windows NT\CurrentVersion', 'CurrentMinorVersionNumber', -1);
     if Result = -1 then
- Result := strToInt(StrAfter('.', RegReadStringDef(HKEY_LOCAL_MACHINE, 'SOFTWARE\Microsoft\Windows NT\CurrentVersion', 'CurrentVersion', intToStr(Win32MajorVersion) + '.' + intToStr(Win32MinorVersion))));
+ Result := strToInt(StrAfterCaseSensitive('.', RegReadStringDef(HKEY_LOCAL_MACHINE, 'SOFTWARE\Microsoft\Windows NT\CurrentVersion', 'CurrentVersion', intToStr(Win32MajorVersion) + '.' + intToStr(Win32MinorVersion))));
   end
   else
     Result := Win32MajorVersion;
--
2.8.2.windows.1

2016-08-03 14:59

 

0001-JEDI-JCL.patch (3,861 bytes)
From a27f0e7d00351135282264f7e49a8c761b0ceb60 Mon Sep 17 00:00:00 2001
From: Bogdan Bot-Rus <Bogdan.Bot-Rus@gfi.com>
Date: Wed, 3 Aug 2016 14:37:50 +0300
Subject: [PATCH 1/1] JEDI JCL   
 http://issuetracker.delphi-jedi.org/view.php?id=6519 Summary 0006519:
 GetWindowsMajorVersionNumber strToInt(StrBefore('.' Crash on Windows Storage
 Server 2012 R2 in JclSysInfo.pas > initialization s Description OS:Windows
 Storage Server 2012 R2
 HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\Windows
 NT\CurrentVersion\CurrentVersion = 6.3
 HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\Windows
 NT\CurrentVersion\ProductName = 'Windows Storage Server 2012 R2 Standard' The
 crash is generated because 'ProductName' <> 'Windows Server 2012 R2'
 GetWindowsMajorVersionNumber calls StrBefore which calls StrFind which calls
 StrIPos which calls StrUpper which calls StrUpperInPlace which calls
 StrCase(S, StrUpOffset) which needs StrCaseMap to be populated. But since
 this all is run as part of the initialization section of JclSysInfo,
 StrCaseMap is not populated yet. Therefore StrUpper returns #0#0#0, StrBefore
 returns '', StrToInt crashes the process.

---
 ThirdParty/JEDI/jcl/common/JclSysInfo.pas | 26 ++++++++++++++++++++++++--
 1 file changed, 24 insertions(+), 2 deletions(-)

diff --git a/ThirdParty/JEDI/jcl/common/JclSysInfo.pas b/ThirdParty/JEDI/jcl/common/JclSysInfo.pas
index 7e4c814..efd4045 100644
--- a/ThirdParty/JEDI/jcl/common/JclSysInfo.pas
+++ b/ThirdParty/JEDI/jcl/common/JclSysInfo.pas
@@ -3874,6 +3874,28 @@ begin
     Result := Win32BuildNumber;
 end;
 
+function StrBeforeCaseSensitive(const SubStr, S: string): string;
+var
+  P: SizeInt;
+begin
+  P := Pos(SubStr, S, 1); //StrFind(SubStr, S, 1);
+  if P <= 0 then
+    Result := S
+  else
+    Result := StrLeft(S, P - 1);
+end;
+
+function StrAfterCaseSensitive(const SubStr, S: string): string;
+var
+  P: SizeInt;
+begin
+  P := Pos(SubStr, S, 1); //StrFind(SubStr, S, 1); // StrFind is case-insensitive pos
+  if P <= 0 then
+    Result := ''           // substr not found -> nothing after it
+  else
+    Result := StrRestOf(S, P + Length(SubStr));
+end;
+
 function GetWindowsMajorVersionNumber: Integer;
 begin
   // Starting with Windows 8.1, the GetVersion(Ex) API is deprecated and will detect the
@@ -3885,7 +3907,7 @@ begin
     // If CurrentMajorVersionNumber not present in registry then use CurrentVersion
     Result := RegReadIntegerDef(HKEY_LOCAL_MACHINE, 'SOFTWARE\Microsoft\Windows NT\CurrentVersion', 'CurrentMajorVersionNumber', -1);
     if Result = -1 then
-      Result := strToInt(StrBefore('.', RegReadStringDef(HKEY_LOCAL_MACHINE, 'SOFTWARE\Microsoft\Windows NT\CurrentVersion', 'CurrentVersion', intToStr(Win32MajorVersion) + '.' + intToStr(Win32MinorVersion))));
+      Result := StrToInt(StrBeforeCaseSensitive('.', RegReadStringDef(HKEY_LOCAL_MACHINE, 'SOFTWARE\Microsoft\Windows NT\CurrentVersion', 'CurrentVersion', intToStr(Win32MajorVersion) + '.' + intToStr(Win32MinorVersion))));
   end
   else
     Result := Win32MajorVersion;
@@ -3902,7 +3924,7 @@ begin
     // If CurrentMinorVersionNumber not present then use CurrentVersion
     Result := RegReadIntegerDef(HKEY_LOCAL_MACHINE, 'SOFTWARE\Microsoft\Windows NT\CurrentVersion', 'CurrentMinorVersionNumber', -1);
     if Result = -1 then
-      Result := strToInt(StrAfter('.', RegReadStringDef(HKEY_LOCAL_MACHINE, 'SOFTWARE\Microsoft\Windows NT\CurrentVersion', 'CurrentVersion', intToStr(Win32MajorVersion) + '.' + intToStr(Win32MinorVersion))));
+      Result := strToInt(StrAfterCaseSensitive('.', RegReadStringDef(HKEY_LOCAL_MACHINE, 'SOFTWARE\Microsoft\Windows NT\CurrentVersion', 'CurrentVersion', intToStr(Win32MajorVersion) + '.' + intToStr(Win32MinorVersion))));
   end
   else
     Result := Win32MajorVersion;
-- 
2.8.2.windows.1

0001-JEDI-JCL.patch (3,861 bytes)

AHUser

2016-08-03 16:46

developer   ~0021315

I fixed this yesterday. The StrAfter/StrBefore have too much overhead for what the GetWindowsMajorVersionNumber/GetWindowsMinorVersionNumber need it, so I replaced it with the "classic" Copy+Pos code.

Issue History

Date Modified Username Field Change
2016-08-03 02:48 intersat2_gmail_com New Issue
2016-08-03 02:48 intersat2_gmail_com File Added: ShouldNotUseStrCaseWithinInitializeSection.png
2016-08-03 02:48 intersat2_gmail_com IDE version => All
2016-08-03 14:58 intersat2_gmail_com Note Added: 0021314
2016-08-03 14:59 intersat2_gmail_com File Added: 0001-JEDI-JCL.patch
2016-08-03 15:00 intersat2_gmail_com Note Edited: 0021314
2016-08-03 16:45 AHUser Relationship added duplicate of 0006489
2016-08-03 16:46 AHUser Note Added: 0021315
2016-08-03 16:46 AHUser Status new => resolved
2016-08-03 16:46 AHUser Resolution open => fixed
2016-08-03 16:46 AHUser Assigned To => AHUser