Ver Fonte

* fixed some record size checks
(some are still broken, but can't be fixed currently because
def.size/sym.getsize return an aint, which means low(aint)
in case of structures with a size = high(aint)+1)

git-svn-id: trunk@7614 -

Jonas Maebe há 18 anos atrás
pai
commit
c77d74127b

+ 4 - 0
.gitattributes

@@ -7370,6 +7370,10 @@ tests/webtbf/tw8780a.pp svneol=native#text/plain
 tests/webtbf/tw8780b.pp svneol=native#text/plain
 tests/webtbf/tw8780c.pp svneol=native#text/plain
 tests/webtbf/tw8781.pp svneol=native#text/plain
+tests/webtbf/tw9039a.pp svneol=native#text/plain
+tests/webtbf/tw9039b.pp svneol=native#text/plain
+tests/webtbf/tw9039c.pp svneol=native#text/plain
+tests/webtbf/tw9039d.pp svneol=native#text/plain
 tests/webtbf/uw0744.pp svneol=native#text/plain
 tests/webtbf/uw0840a.pp svneol=native#text/plain
 tests/webtbf/uw0840b.pp svneol=native#text/plain

+ 20 - 7
compiler/symtable.pas

@@ -791,12 +791,14 @@ implementation
               begin
                 databitsize:=_datasize*8;
                 sym.fieldoffset:=databitsize;
+                if (l>high(aint) div 8) then
+                  Message(sym_e_segment_too_large);
                 l:=l*8;
               end;
             { bit packed records are limited to high(aint) bits }
             { instead of bytes to avoid double precision        }
             { arithmetic in offset calculations                 }
-            if (int64(l)+sym.fieldoffset)>high(aint) then
+            if int64(l)>high(aint)-sym.fieldoffset then
               begin
                 Message(sym_e_segment_too_large);
                 _datasize:=high(aint);
@@ -843,7 +845,7 @@ implementation
           varalignfield:=used_align(varalign,current_settings.alignment.recordalignmin,fieldalignment);
 
         sym.fieldoffset:=align(_datasize,varalignfield);
-        if (int64(l)+sym.fieldoffset)>high(aint) then
+        if l>high(aint)-sym.fieldoffset then
           begin
             Message(sym_e_segment_too_large);
             _datasize:=high(aint);
@@ -934,7 +936,8 @@ implementation
         def : tdef;
         i,
         varalignrecord,varalign,
-        storesize,storealign : longint;
+        storesize,storealign : aint;
+        bitsize: aint;
       begin
         storesize:=_datasize;
         storealign:=fieldalignment;
@@ -963,7 +966,16 @@ implementation
                 { bit packed records are limited to high(aint) bits }
                 { instead of bytes to avoid double precision        }
                 { arithmetic in offset calculations                 }
-                if databitsize>high(aint) then
+                if is_ordinal(tfieldvarsym(sym).vardef) then
+                  bitsize:=tfieldvarsym(sym).getpackedbitsize
+                else
+                  begin
+                    bitsize:=tfieldvarsym(sym).getsize;
+                    if (bitsize>high(aint) div 8) then
+                      Message(sym_e_segment_too_large);
+                    bitsize:=bitsize*8;
+                  end;
+                if bitsize>high(aint)-databitsize then
                   begin
                     Message(sym_e_segment_too_large);
                     _datasize:=high(aint);
@@ -978,12 +990,13 @@ implementation
               end
             else
               begin
-                _datasize:=tfieldvarsym(sym).fieldoffset+offset;
-                if _datasize>high(aint) then
+                if tfieldvarsym(sym).getsize>high(aint)-_datasize then
                   begin
                     Message(sym_e_segment_too_large);
                     _datasize:=high(aint);
-                  end;
+                  end
+                else
+                  _datasize:=tfieldvarsym(sym).fieldoffset+offset;
                 { update address }
                 tfieldvarsym(sym).fieldoffset:=_datasize;
                 { update alignment of this record }

+ 17 - 0
tests/webtbf/tw9039a.pp

@@ -0,0 +1,17 @@
+{ %fail }
+
+{ the reason this compiles is that tdef.size and tabstractvarsym.getsize }
+{ both return an aint, and then the size of ta is reported as low(aint)  }
+
+type
+  ta = array[0..high(ptrint)] of byte;
+  tr = packed record
+    a: byte;
+    case byte of
+      0: (l: longint);
+      1: (e: ta);
+  end;
+
+begin
+  writeln(sizeof(ta));
+end.

+ 17 - 0
tests/webtbf/tw9039b.pp

@@ -0,0 +1,17 @@
+{ %fail }
+
+{ the reason this compiles is that tdef.size and tabstractvarsym.getsize }
+{ both return an aint, and then the size of ta is reported as low(aint)  }
+
+type
+  ta = array[0..high(ptrint)] of byte;
+  tr = bitpacked record
+    a: byte;
+    case byte of
+      0: (l: longint);
+      1: (e: ta);
+  end;
+
+begin
+  writeln(sizeof(ta));
+end.

+ 15 - 0
tests/webtbf/tw9039c.pp

@@ -0,0 +1,15 @@
+{ the reason this compiles is that tdef.size and tabstractvarsym.getsize }
+{ both return an aint, and then the size of ta is reported as low(aint)  }
+
+type
+  ta = array[1..high(ptrint)-4] of byte;
+  tr = packed record
+    l: longint;
+    case byte of
+      0: (l: longint);
+      1: (e: ta);
+  end;
+
+begin
+  writeln(sizeof(ta));
+end.

+ 12 - 0
tests/webtbf/tw9039d.pp

@@ -0,0 +1,12 @@
+type
+  ta = array[1..high(ptrint) div 8-1] of byte;
+  tr = bitpacked record
+    a: byte;
+    case byte of
+      0: (l: longint);
+      1: (e: ta);
+  end;
+
+begin
+  writeln(sizeof(ta));
+end.