|
@@ -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.
|