Browse Source

* patch by J. Gareth Moreton which avoids that the optimizer causes reads of invalid memory, resolves #35187

git-svn-id: trunk@41667 -
florian 6 years ago
parent
commit
d657373933
3 changed files with 120 additions and 7 deletions
  1. 1 0
      .gitattributes
  2. 7 7
      compiler/x86/aoptx86.pas
  3. 112 0
      tests/webtbs/tw35187.pp

+ 1 - 0
.gitattributes

@@ -16551,6 +16551,7 @@ tests/webtbs/tw3506.pp svneol=native#text/plain
 tests/webtbs/tw35139.pp svneol=native#text/plain
 tests/webtbs/tw35139a.pp svneol=native#text/plain
 tests/webtbs/tw35149.pp svneol=native#text/plain
+tests/webtbs/tw35187.pp svneol=native#text/pascal
 tests/webtbs/tw3523.pp svneol=native#text/plain
 tests/webtbs/tw3529.pp svneol=native#text/plain
 tests/webtbs/tw3531.pp svneol=native#text/plain

+ 7 - 7
compiler/x86/aoptx86.pas

@@ -3484,44 +3484,44 @@ unit aoptx86;
                       MatchOpType(taicpu(hp1),top_const,top_reg) and
                       (taicpu(hp1).oper[1]^.reg = taicpu(p).oper[1]^.reg) then
                       begin
-                        taicpu(p).opcode := A_MOV;
+                        //taicpu(p).opcode := A_MOV;
                         case taicpu(p).opsize Of
                           S_BL:
                             begin
                               DebugMsg(SPeepholeOptimization + 'var13',p);
-                              taicpu(p).changeopsize(S_L);
+                              taicpu(hp1).changeopsize(S_L);
                               taicpu(hp1).loadConst(0,taicpu(hp1).oper[0]^.val and $ff);
                             end;
                           S_WL:
                             begin
                               DebugMsg(SPeepholeOptimization + 'var14',p);
-                              taicpu(p).changeopsize(S_L);
+                              taicpu(hp1).changeopsize(S_L);
                               taicpu(hp1).loadConst(0,taicpu(hp1).oper[0]^.val and $ffff);
                             end;
                           S_BW:
                             begin
                               DebugMsg(SPeepholeOptimization + 'var15',p);
-                              taicpu(p).changeopsize(S_W);
+                              taicpu(hp1).changeopsize(S_W);
                               taicpu(hp1).loadConst(0,taicpu(hp1).oper[0]^.val and $ff);
                             end;
 {$ifdef x86_64}
                           S_BQ:
                             begin
                               DebugMsg(SPeepholeOptimization + 'var16',p);
-                              taicpu(p).changeopsize(S_Q);
+                              taicpu(hp1).changeopsize(S_Q);
                               taicpu(hp1).loadConst(
                                 0, taicpu(hp1).oper[0]^.val and $ff);
                             end;
                           S_WQ:
                             begin
                               DebugMsg(SPeepholeOptimization + 'var17',p);
-                              taicpu(p).changeopsize(S_Q);
+                              taicpu(hp1).changeopsize(S_Q);
                               taicpu(hp1).loadConst(0, taicpu(hp1).oper[0]^.val and $ffff);
                             end;
                           S_LQ:
                             begin
                               DebugMsg(SPeepholeOptimization + 'var18',p);
-                              taicpu(p).changeopsize(S_Q);
+                              taicpu(hp1).changeopsize(S_Q);
                               taicpu(hp1).loadConst(
                                 0, taicpu(hp1).oper[0]^.val and $ffffffff);
                             end;

+ 112 - 0
tests/webtbs/tw35187.pp

@@ -0,0 +1,112 @@
+program tw35187;
+
+{ %cpu=i386,x86_64 }
+{ %opt=-O1 }
+
+{ NOTE: SIGSEGV won't trigger if GetMem is used because it allocates pages from a large pre-reserved heap. [Kit] }
+
+{$IFDEF TARGET_VALID}
+{$UNDEF TARGET_VALID}
+{$ENDIF TARGET_VALID}
+
+{$IFDEF WINDOWS}
+uses
+  Windows;
+{$DEFINE TARGET_VALID}
+{$ENDIF}
+{$IFDEF UNIX}
+uses
+  BaseUnix, SysCall;
+
+function fpmprotect(Addr: Pointer; Len: PtrUInt; Prot: LongInt): LongInt; inline;
+begin
+  fpmprotect := Do_SysCall(syscall_nr_mprotect, TSysParam(Addr), Len, Prot);
+end;
+{$DEFINE TARGET_VALID}
+{$ENDIF}
+
+{$IFNDEF TARGET_VALID}
+{$ERROR No memory allocation routine available }
+{$ENDIF TARGET_VALID}
+
+const
+  TestBlock: packed array[0..127] of Char = 'The quick brown fox jumps over the lazy dog, Victor jagt zw'#148'lf Boxk'#132'mpfer quer '#129'ber den gro'#225'en Sylter Deich.'#10#13'0123456789?!"#%'#251#253#252;
+
+  Expected: packed array[0..255] of Char = '54686520717569636B2062726F776E20666F78206A756D7073206F76657220746865206C617A7920646F672C20566963746F72206A616774207A77946C6620426F786B846D70666572207175657220816265722064656E2067726FE1656E2053796C7465722044656963682E0A0D303132333435363738393F21222325FBFDFC';
+
+  HexDigits: packed array[0..$F] of Char = '0123456789ABCDEF';
+
+var
+  Buf: packed array[0..255] of Char;
+  HexPtr: PChar;
+  P: PByte;
+  I: DWord;
+  HeapBlock, HeapMarker: PByte;
+begin
+  WriteLn(TestBlock);
+  FillChar(Buf, SizeOf(Buf), 0);
+
+  { Reserve two 4K memory pages: one that is read-write followed by one that
+    has no access rights at all and will trigger SIGSEGV if encroached }
+{$IFDEF WINDOWS}
+  HeapBlock := VirtualAlloc(
+                 VirtualAlloc(nil, 8192, MEM_RESERVE, PAGE_READWRITE),
+                 4096,
+                 MEM_COMMIT,
+                 PAGE_READWRITE
+               );
+  if not Assigned(HeapBlock) then
+    begin
+      WriteLn('Memory allocation failure');
+      Halt(1);
+    end;
+  HeapMarker := HeapBlock + 3968; { 4096 - 128 }
+{$ENDIF WINDOWS}
+{$IFDEF UNIX}
+  HeapBlock := fpmmap(nil, 8192, PROT_NONE, MAP_ANON or MAP_PRIVATE, -1, 0);
+  if not Assigned(HeapBlock) or (fpmprotect(HeapBlock, 4096, PROT_READ or PROT_WRITE) <> 0) then
+    begin
+      WriteLn('Memory allocation failure');
+      Halt(1);
+    end;
+
+  HeapMarker := HeapBlock + 3968; { 4096 - 128 }
+{$ENDIF UNIX}
+
+  Move(TestBlock, HeapMarker^, SizeOf(TestBlock));
+  HexPtr := @Buf;
+
+  for I := 0 to SizeOf(TestBlock) - 1 do
+  begin
+    P := HeapMarker + I;
+
+    HexPtr^ := HexDigits[P^ shr 4]; { first nybble }
+    Write(HexPtr^);
+    Inc(HexPtr);
+
+    { #35187: This instruction causes an access violation on the last byte
+        because it tries to read a word instead of a byte. }
+
+    HexPtr^ := HexDigits[P^ and $F]; { second nybble }
+    Write(HexPtr^);
+    Inc(HexPtr);
+  end;
+
+{$IFDEF WINDOWS}
+  VirtualFree(HeapBlock, 0, MEM_RELEASE);
+{$ENDIF WINDOWS}
+{$IFDEF UNIX}
+  fpmunmap(HeapBlock, 8192);
+{$ENDIF UNIX}
+
+  WriteLn();
+
+  for I := 0 to SizeOf(TestBlock) - 1 do
+    if Buf[I] <> Expected[I] then
+    begin
+      WriteLn('Error at index ', I, '; expected ', Expected[I], ' got ', Buf[I]);
+      Halt(1);
+    end;
+
+  WriteLn('ok');
+end.