Bug 14201

Summary: gas 2.19.51, Assertion failure when declaring large array: sb_build at /netrel/src/binutils-2.19.51-1/gas/sb.c line 62.
Product: binutils Reporter: mpolon
Component: gasAssignee: Alan Modra <amodra>
Severity: normal    
Priority: P2    
Version: pre-2.15   
Target Milestone: ---   
Host: Target:
Build: Last reconfirmed:

Description mpolon 2012-06-04 22:55:24 UTC
Trying to pad memory in the data section with zeros, using the following assembly file results in a "gas" assertion. My platform is a PC, running cygwin under Win7 64-bit (i686 target).

$ cat pad_data.s
        .file   "pad_data.c"
        .align  4
        .global _pad_data
        .rept   (0x40000*400) 
        .long 0

Below is my "as" command line as well as output:
$ as -o pad_data.o pad_data.s
pad_data.s: Assembler messages:
pad_data.s:9: Internal error!
Assertion failure in sb_build at /netrel/src/binutils-2.19.51-1/gas/sb.c line 62.
Please report this bug.

One would expect that if the "rept" directive value is too large that "as" would fail with an error instead of the assertion failure.

Note that using much smaller sizes in the "rept" directive works without error.
Comment 1 Sourceware Commits 2012-06-07 12:47:27 UTC
CVSROOT:	/cvs/src
Module name:	src
Changes by:	amodra@sourceware.org	2012-06-07 12:47:23

Modified files:
	gas            : ChangeLog app.c as.c as.h input-file.c 
	                 input-file.h input-scrub.c macro.c macro.h 
	                 read.c sb.c sb.h 

Log message:
	PR gas/14201
	* sb.h (sb_max_power_two): Delete.
	(struct sb): Delete "item" and "pot".  Make "len" a size_t.  Add "max".
	(sb_element): Delete.
	(sb_add_char, sb_add_buffer, sb_skip_comma, sb_skip_write): Update
	* sb.c (string_count, free_list): Delete.
	(sb_build, sb_kill, sb_check): Rewrite.
	(scrub_from_sb, sb_add_char, sb_add_string, sb_add_buffer,
	sb_skip_white, sb_skip_comma): Replace assorted int params,
	vars and return types with size_t.
	* input-scrub.c: Likewise.
	* macro.c: Likewise.
	* macro.h: Likewise.
	* as.c: Likewise.
	* as.h: Likewise.
	* input-file.h: Likewise.
	* input-file.c: Likewise.
	* read.c: Likewise.
	* app.c: ..or ptrdiff_t.
	* input-file.c (input_file_get): Use ferror.
	(input_file_give_next_buffer): Use input_file_get.

Comment 2 Alan Modra 2012-06-07 12:49:04 UTC
Fixed mainline
Comment 3 Sourceware Commits 2012-06-07 13:47:18 UTC
CVSROOT:	/cvs/src
Module name:	src
Changes by:	hjl@sourceware.org	2012-06-07 13:47:14

Modified files:
	gas/testsuite  : ChangeLog 
	gas/testsuite/gas/all: gas.exp 
Added files:
	gas/testsuite/gas/all: rept.d rept.s 

Log message:
	Add a testcase for PR gas/14201
	PR gas/14201
	* gas/all/gas.exp: Run rept.
	* gas/all/rept.d: New file.
	* gas/all/rept.s: Likewise.

Comment 4 H.J. Lu 2012-06-07 17:06:12 UTC
On Linux/ia32 with GCC 4.1.2, I got

../as-new   -o dump.o /net/gnu-6/export/gnu/import/git/binutils/gas/testsuite/gas/i386/rept.s
Executing on host: sh -c {../as-new   -o dump.o /net/gnu-6/export/gnu/import/git/binutils/gas/testsuite/gas/i386/rept.s 2>&1}  /dev/null gas.out (timeout = 300)

../as-new: out of memory allocating 1073741825 bytes after a total of 135168 bytes
Comment 5 H.J. Lu 2012-06-07 17:52:34 UTC
The failure is OS dependent:

#0  sb_scrub_and_add_sb (ptr=0x8196128, s=0xbfffe670)
    at /net/gnu-6/export/gnu/import/git/binutils/gas/sb.c:102
#1  0x0805b7c4 in input_scrub_include_sb (from=0xbfffe670, 
    position=0x81a097b "", is_expansion=1)
    at /net/gnu-6/export/gnu/import/git/binutils/gas/input-scrub.c:287
#2  0x08065bee in do_repeat (count=-1, start=0x812e9cd "REPT", 
    end=0x812e9c8 "ENDR")
    at /net/gnu-6/export/gnu/import/git/binutils/gas/read.c:3216
#3  0x08065b3d in s_rept (ignore=0)
    at /net/gnu-6/export/gnu/import/git/binutils/gas/read.c:3191
#4  0x08062be9 in read_a_source_file (name=0xbfffea19 "/tmp/x.s")
    at /net/gnu-6/export/gnu/import/git/binutils/gas/read.c:1076
#5  0x0804caa3 in perform_an_assembly_pass (argc=0, argv=0x819c7dc)
    at /net/gnu-6/export/gnu/import/git/binutils/gas/as.c:1095
#6  0x0804cdf0 in main (argc=2, argv=0x819c7d8)
    at /net/gnu-6/export/gnu/import/git/binutils/gas/as.c:1242
(gdb) f 2
#2  0x08065bee in do_repeat (count=-1, start=0x812e9cd "REPT", 
    end=0x812e9c8 "ENDR")
    at /net/gnu-6/export/gnu/import/git/binutils/gas/read.c:3216
3216	  input_scrub_include_sb (&many, input_line_pointer, 1);
(gdb) p many
$19 = {
  ptr = 0x37c3c008 "\n .byte 0\n\n .byte 0\n\n .byte 0\n\n .byte 0\n\n .byte 0\n\n .byte 0\n\n .byte 0\n\n .byte 0\n\n .byte 0\n\n .byte 0\n\n .byte 0\n\n .byte 0\n\n .byte 0\n\n .byte 0\n\n .byte 0\n\n .byte 0\n\n .byte 0\n\n .byte 0\n\n .byte 0\n\n .byte 0\n"..., len = 550502400, max = 1073741824}

While holding a 500M sb, we are allocating another 500M sb.  And
the first 500M sb will be freed right after it:

  input_scrub_include_sb (&many, input_line_pointer, 1);
  sb_kill (&many);

Why not reuse the first 500M sb?
Comment 6 Alan Modra 2012-06-08 02:10:26 UTC
An "Out of memory" error is exactly what you should get from a test that uses a ridiculous repeat count.