diff --git a/.gitattributes b/.gitattributes index 44633b333d..618dfbf0f5 100644 --- a/.gitattributes +++ b/.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 diff --git a/compiler/symtable.pas b/compiler/symtable.pas index 09ce021221..e9bc0641c9 100644 --- a/compiler/symtable.pas +++ b/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 } diff --git a/tests/webtbf/tw9039a.pp b/tests/webtbf/tw9039a.pp new file mode 100644 index 0000000000..aed72c3be9 --- /dev/null +++ b/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. diff --git a/tests/webtbf/tw9039b.pp b/tests/webtbf/tw9039b.pp new file mode 100644 index 0000000000..571ed898df --- /dev/null +++ b/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. diff --git a/tests/webtbf/tw9039c.pp b/tests/webtbf/tw9039c.pp new file mode 100644 index 0000000000..b36d500216 --- /dev/null +++ b/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. diff --git a/tests/webtbf/tw9039d.pp b/tests/webtbf/tw9039d.pp new file mode 100644 index 0000000000..b8308c8153 --- /dev/null +++ b/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.