Bug 112347 - [14 regression] ICE on jemalloc-5.3.0: Segmentation fault around convert_for_assignment()
Summary: [14 regression] ICE on jemalloc-5.3.0: Segmentation fault around convert_for_...
Status: RESOLVED FIXED
Alias: None
Product: gcc
Classification: Unclassified
Component: c (show other bugs)
Version: 14.0
: P3 normal
Target Milestone: 14.0
Assignee: Martin Uecker
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2023-11-02 09:49 UTC by Sergei Trofimovich
Modified: 2023-11-04 08:22 UTC (History)
3 users (show)

See Also:
Host:
Target:
Build:
Known to work:
Known to fail:
Last reconfirmed: 2023-11-03 00:00:00


Attachments
patch (1.91 KB, text/plain)
2023-11-02 12:22 UTC, Martin Uecker
Details
patch (1.91 KB, text/plain)
2023-11-02 12:24 UTC, Martin Uecker
Details
patch (794 bytes, text/plain)
2023-11-02 12:27 UTC, Martin Uecker
Details

Note You need to log in before you can comment on or make changes to this bug.
Description Sergei Trofimovich 2023-11-02 09:49:18 UTC
Noticed ICE on today's `gcc-master` r14-5073-g36a26298ec7dfc when building jemalloc-5.3.0. Extracted the following example:

    // $ cat a.c.c
    int * mallocx(unsigned long) __attribute__((malloc)) __attribute__((alloc_size(1)));
    void test_oom(void) { void *a_ = mallocx(1); }

Crashing:

$ gcc/xgcc -Bgcc -std=gnu11 -Wextra -c /tmp/a.c.c

/tmp/a.c.c: In function ‘test_oom’:
/tmp/a.c.c:2:1: internal compiler error: Segmentation fault
    2 | void test_oom(void) { void *a_ = mallocx(1); }
      | ^~~~
0x225a30b diagnostic_impl(rich_location*, diagnostic_metadata const*, int, char const*, __va_list_tag (*) [1], diagnostic_t)
        ???:0
0x225b12e internal_error(char const*, ...)
        ???:0
0xee1c4f crash_signal(int)
        ???:0
0x7bfff6 convert_for_assignment(unsigned int, unsigned int, tree_node*, tree_node*, tree_node*, impl_conv, bool, tree_node*, tree_node*, int, int)
        ???:0
0x7cc38d digest_init(unsigned int, tree_node*, tree_node*, tree_node*, bool, bool, bool, bool, bool, bool)
        ???:0
0x7cf3af store_init_value(unsigned int, tree_node*, tree_node*, tree_node*)
        ???:0
0x795284 finish_decl(tree_node*, unsigned int, tree_node*, tree_node*, tree_node*)
        ???:0
0x817385 c_parser_declaration_or_fndef(c_parser*, bool, bool, bool, bool, bool, tree_node**, vec<c_token, va_heap, vl_ptr>*, bool, tree_node*, oacc_routine_data*, bool*)
        ???:0
0x814efb c_parser_compound_statement_nostart(c_parser*)
        ???:0
0x81573f c_parser_compound_statement(c_parser*, unsigned int*)
        ???:0
0x81719a c_parser_declaration_or_fndef(c_parser*, bool, bool, bool, bool, bool, tree_node**, vec<c_token, va_heap, vl_ptr>*, bool, tree_node*, oacc_routine_data*, bool*)
        ???:0
0x821ab9 c_parser_external_declaration(c_parser*)
        ???:0
0x822610 c_parse_file()
        ???:0
0x8a274f c_common_parse_file()
        ???:0

$ gcc/xgcc -Bgcc -v
Reading specs from gcc/specs
COLLECT_GCC=gcc/xgcc
COLLECT_LTO_WRAPPER=gcc/lto-wrapper
Target: x86_64-pc-linux-gnu
Configured with: /home/slyfox/dev/git/gcc/configure --disable-multilib --disable-bootstrap --disable-lto --disable-libsanitizer --enable-languages=c CFLAGS='-O1 -g0' CXXFLAGS='-O1 -g0' LDFLAGS='-O1 -g0'
Thread model: posix
Supported LTO compression algorithms: zlib
gcc version 14.0.0 20231102 (experimental) (GCC)
Comment 1 Sergei Trofimovich 2023-11-02 09:53:46 UTC
r14-5059-gd880e093d92084 "c: Add Walloc-size to warn about insufficient size in allocations [PR71219]" looks relevant.
Comment 2 Sergei Trofimovich 2023-11-02 10:00:44 UTC
A bit of debugging:

Program received signal SIGSEGV, Segmentation fault.
0x00000000007bfff6 in convert_for_assignment (location=location@entry=263654, expr_loc=expr_loc@entry=0, type=type@entry=0x7fffea029000, rhs=0x7fffea000508,
    origtype=origtype@entry=0x0, errtype=errtype@entry=ic_init, null_pointer_constant=false, fundecl=0x0, function=0x0, parmnum=0, warnopt=0)
    at /home/slyfox/dev/git/gcc/gcc/c/c-typeck.cc:7370
warning: Source file is more recent than executable.
7370                      && INTEGER_CST == TREE_CODE (TYPE_SIZE_UNIT (ttl))
(gdb) bt
#0  0x00000000007bfff6 in convert_for_assignment (location=location@entry=263654, expr_loc=expr_loc@entry=0, type=type@entry=0x7fffea029000, rhs=0x7fffea000508,
    origtype=origtype@entry=0x0, errtype=errtype@entry=ic_init, null_pointer_constant=false, fundecl=0x0, function=0x0, parmnum=0, warnopt=0)
    at /home/slyfox/dev/git/gcc/gcc/c/c-typeck.cc:7370

(gdb) call debug_tree(ttl)
 <void_type 0x7fffea021f18 void VOID
    align:8 warn_if_not_align:0 symtab:0 alias-set -1 canonical-type 0x7fffea021f18
    pointer_to_this <pointer_type 0x7fffea029000>>
Comment 3 Martin Uecker 2023-11-02 10:24:30 UTC
Thanks for reporting. I will fix this.
Comment 4 Martin Uecker 2023-11-02 12:22:28 UTC
Created attachment 56489 [details]
patch

This should fix it. I am running some tests and will commit this.
Comment 5 Martin Uecker 2023-11-02 12:24:34 UTC
Created attachment 56490 [details]
patch

Correct attachment.
Comment 6 Martin Uecker 2023-11-02 12:27:42 UTC
Created attachment 56491 [details]
patch

Ok, let's try again...
Comment 7 David Binderman 2023-11-02 12:33:56 UTC
Another test case:

parse_args(char (**child_args_ptr_ptr)[]) {
  *child_args_ptr_ptr = calloc(1, sizeof(char));
}

when compiled with -Wextra:

$ ~/gcc/results/bin/gcc -c -Wextra bug975.c
bug975.c:1:1: warning: return type defaults to ‘int’ [-Wimplicit-int]
    1 | parse_args(char (**child_args_ptr_ptr)[]) {
      | ^~~~~~~~~~
bug975.c: In function ‘parse_args’:
bug975.c:2:25: warning: implicit declaration of function ‘calloc’ [-Wimplicit-function-declaration]
    2 |   *child_args_ptr_ptr = calloc(1, sizeof(char));
      |                         ^~~~~~
bug975.c:1:1: note: include ‘<stdlib.h>’ or provide a declaration of ‘calloc’
  +++ |+#include <stdlib.h>
    1 | parse_args(char (**child_args_ptr_ptr)[]) {
bug975.c:2:25: warning: incompatible implicit declaration of built-in function ‘calloc’ [-Wbuiltin-declaration-mismatch]
    2 |   *child_args_ptr_ptr = calloc(1, sizeof(char));
      |                         ^~~~~~
bug975.c:2:25: note: include ‘<stdlib.h>’ or provide a declaration of ‘calloc’
bug975.c:2:3: internal compiler error: Segmentation fault
    2 |   *child_args_ptr_ptr = calloc(1, sizeof(char));
      |   ^
0xebd319 crash_signal(int)
	../../trunk.year/gcc/toplev.cc:315
0x74ffd9 convert_for_assignment(unsigned int, unsigned int, tree_node*, tree_node*, tree_node*, impl_conv, bool, tree_node*, tree_node*, int, int)
	../../trunk.year/gcc/c/c-typeck.cc:7370
Comment 8 Sergei Trofimovich 2023-11-02 13:33:22 UTC
(In reply to Martin Uecker from comment #6)
> Created attachment 56491 [details]
> patch
> 
> Ok, let's try again...

The change fixes jemalloc and boehm-gc builds for me. Thank you!
Comment 9 GCC Commits 2023-11-02 13:55:34 UTC
The master branch has been updated by Martin Uecker <uecker@gcc.gnu.org>:

https://gcc.gnu.org/g:f432a594fe6d3a0de1330ba69200d158e6248083

commit r14-5084-gf432a594fe6d3a0de1330ba69200d158e6248083
Author: Martin Uecker <uecker@tugraz.at>
Date:   Thu Nov 2 13:12:15 2023 +0100

    c: Add missing conditions in Walloc-size to avoid ICEs [PR112347]
    
    Fix ICE because of forgotten checks for pointers to void
    and incomplete arrays.
    
    Committed as obvious.
    
            PR c/112347
    
    gcc/c:
            * c-typeck.cc (convert_for_assignment): Add missing check.
    
    gcc/testsuite:
    
            * gcc.dg/Walloc-size-3.c: New test.
Comment 10 David Binderman 2023-11-02 16:24:18 UTC
When this patch was tested, did that include a build of libgfortran ?

I am getting some strange new warnings:

../../../trunk.year/libgfortran/io/async.c:265:24: warning: allocation of insufficient size ‘1’ for type ‘transfer_queue’ with size ‘80’ [-Walloc-size]
../../../trunk.year/libgfortran/io/async.c:287:24: warning: allocation of insufficient size ‘1’ for type ‘transfer_queue’ with size ‘80’ [-Walloc-size]
../../../trunk.year/libgfortran/io/async.c:311:24: warning: allocation of insufficient size ‘1’ for type ‘transfer_queue’ with size ‘80’ [-Walloc-size]
../../../trunk.year/libgfortran/io/async.c:331:24: warning: allocation of insufficient size ‘1’ for type ‘transfer_queue’ with size ‘80’ [-Walloc-size]

The code looks legal to me. Here is the first one:

  transfer_queue *tq = calloc (sizeof (transfer_queue), 1);
Comment 11 Martin Uecker 2023-11-02 18:58:59 UTC
In this case this is by design because the size of an element should be second argument to calloc. ("The calloc function allocates space for an array of nmemb objects, each of whose size is size.")
Comment 12 Martin Uecker 2023-11-03 07:53:56 UTC
I filed a bug for libfortran: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=112364
Comment 13 David Binderman 2023-11-03 09:54:09 UTC
I have been trying to get this C++ code to produce the new warning:

#include <cstdlib>

struct S
{
	int a[ 10];
	float * b[ 20];
};

extern void g( S * ps);

void f( int n)
{
	S * ps = (S *) calloc( sizeof( S), 1);
	g( ps);

	S * ps2 = (S *) calloc( 1, sizeof( S));
	g( ps2);

	S * ps3 = (S *) calloc( 1, sizeof( S) / 2);
	g( ps3);
}

$ ~/gcc/results/bin/g++ -g -O2 -Wall -Wextra -Walloc-size -c nov2b.cc
cc1plus: warning: command-line option ‘-Walloc-size’ is valid for C/ObjC but not for C++
nov2b.cc: In function ‘void f(int)’:
nov2b.cc:12:13: warning: unused parameter ‘n’ [-Wunused-parameter]
   12 | void f( int n)
      |         ~~~~^
$ ~/gcc/results/bin/g++ -v
Using built-in specs.
COLLECT_GCC=/home/dcb38/gcc/results/bin/g++
COLLECT_LTO_WRAPPER=/home/dcb38/gcc/results.20231102.asan.ubsan/libexec/gcc/x86_64-pc-linux-gnu/14.0.0/lto-wrapper
Target: x86_64-pc-linux-gnu
Configured with: ../trunk.year/configure --prefix=/home/dcb38/gcc/results.20231102.asan.ubsan --disable-multilib --disable-bootstrap --with-build-config=bootstrap-asan --with-build-config=bootstrap-ubsan --with-pkgversion=01c18f58d37865d5 --enable-checking=df,extra,fold,rtl,yes --enable-languages=c,c++,fortran
Thread model: posix
Supported LTO compression algorithms: zlib zstd
gcc version 14.0.0 20231102 (experimental) (01c18f58d37865d5) 
$ 

I think calloc is available in C++, so the warning is wrong.
Comment 14 Martin Uecker 2023-11-03 11:02:51 UTC
"I think calloc is available in C++, so the warning is wrong."

I am happy to revise the warning if it is wrong or annoying, but I do not understand what C++ has to do with this.
Comment 15 David Binderman 2023-11-03 11:06:23 UTC
(In reply to Martin Uecker from comment #14)
> I am happy to revise the warning if it is wrong or annoying, but I do not
> understand what C++ has to do with this.

In file gcc/c-family/c.opt, is the new text

Walloc-size
C ObjC Var(warn_alloc_size) Warning LangEnabledBy(C ObjC, Wextra)
Warn when allocating insufficient storage for the target type of the assigned pointer.

IMHO, it should say:

Walloc-size
C ObjC Var(warn_alloc_size) Warning LangEnabledBy(C ObjC C++, Wextra)
Warn when allocating insufficient storage for the target type of the assigned pointer.
Comment 16 Martin Uecker 2023-11-03 11:22:24 UTC

I agree that the C++ should have this warning as well, although it seems less important there. This would be an enhancement request for the C++ FE.
Comment 17 Sam James 2023-11-03 11:55:00 UTC
I think this bug is done, anyway?
Comment 18 Martin Uecker 2023-11-03 12:12:21 UTC
I think this can be closed.
Comment 19 Sam James 2023-11-03 12:15:33 UTC
Thanks! Martin, IIRC you have commit access. If you change your email on BZ to <whatever your sourceware login name is>@gcc.gnu.org, you will get editbugs permissions on Bugzilla.
Comment 20 Martin Uecker 2023-11-03 12:17:10 UTC
Ah, this is how it works. Thanks!
Comment 21 David Binderman 2023-11-04 08:22:45 UTC
(In reply to Martin Uecker from comment #16)
> I agree that the C++ should have this warning as well, although it seems
> less important there. This would be an enhancement request for the C++ FE.

See 112377.