Summary: | warning: array subscript is above array bounds at O2 with sin6_addr | ||
---|---|---|---|
Product: | gcc | Reporter: | Dan McGee <dpmcgee> |
Component: | middle-end | Assignee: | Not yet assigned to anyone <unassigned> |
Status: | RESOLVED FIXED | ||
Severity: | normal | CC: | chantry.xavier, msebor, trevor |
Priority: | P3 | Keywords: | diagnostic |
Version: | 4.5.2 | ||
Target Milestone: | --- | ||
Host: | x86_64-unknown-linux-gnu | Target: | x86_64-unknown-linux-gnu |
Build: | x86_64-unknown-linux-gnu | Known to work: | |
Known to fail: | 7.2.0, 8.0 | Last reconfirmed: | 2011-01-25 11:24:58 |
Bug Depends on: | |||
Bug Blocks: | 56456 | ||
Attachments: |
Preprocessed test case
simpler testcase |
Description
Dan McGee
2011-01-23 00:10:42 UTC
Also of note is the commented bit in the test case- if you instead dereference the s6_addr bit of the union, it all works without warnings. In the preprocessed source, replace ap = (char *)&u.sin6.sin6_addr; with: ap = (char *)&u.sin6.sin6_addr.__in6_u.__u6_addr8; (In reply to comment #1) > Also of note is the commented bit in the test case- if you instead dereference > the s6_addr bit of the union, it all works without warnings. > > In the preprocessed source, replace > ap = (char *)&u.sin6.sin6_addr; > > with: > ap = (char *)&u.sin6.sin6_addr.__in6_u.__u6_addr8; Actually it works with any member from __in6.u union. It seems gcc gets confused with the other anonymous union, and use the size of struct sockaddr instead of struct sockaddr_in6. I've got a simpler testcase which shows another interesting information : gcc gets confused when the sign of ap is the same as the size of the smallest struct/array of the union, and different from the sign of the big member that should be used. Created attachment 23084 [details]
simpler testcase
$ gcc -O3 -Wall -c small-test.c
small-test.c: In function 'main':
small-test.c:18:51: warning: array subscript is above array bounds
small-test.c:18:43: warning: array subscript is above array bounds
small-test.c:18:35: warning: array subscript is above array bounds
so gcc seems to think that the size of ap is 13 instead of 16.
It's important that ap and sa_data are both char, and u6_addr8 is unsigned char.
Same warning if ap and sa_data are unsigned char and u6_addr8 is char.
But other combinations apparently do not give any warning.
VRP sees <bb 2>: D.2725_3 = u.sa_data[15]; D.2726_4 = (int) D.2725_3; D.2728_6 = u.sa_data[14]; D.2729_7 = (int) D.2728_6; ... D.2769_47 = u.sa_data[0]; D.2770_48 = (int) D.2769_47; test_func (0, D.2770_48, D.2768_46, D.2765_43, D.2762_40, D.2759_37, D.2756_34, D.2753_31, D.2750_28, D.2747_25, D.2744_22, D.2741_19, D.2738_16, D.2735_13, D.2732_10, D.2729_7, D.2726_4); return 0; because of our fancy way of re-building non-addressed components. With 4.6 the warning is gone and we instead have (thanks to MEM-REF): <bb 2>: D.2695_3 = MEM[(char *)&u + 15B]; D.2696_4 = (int) D.2695_3; D.2698_6 = MEM[(char *)&u + 14B]; D.2699_7 = (int) D.2698_6; ... D.2740_48 = (int) D.2739_47; test_func (0, D.2740_48, D.2738_46, D.2735_43, D.2732_40, D.2729_37, D.2726_34, D.2723_31, D.2720_28, D.2717_25, D.2714_22, D.2711_19, D.2708_16, D.2705_13, D.2702_10, D.2699_7, D.2696_4); return 0; thus, no more array access and still non-address-taken u. 4.4 also warns about small-test.c: In function 'main': small-test.c:18: warning: array subscript is above array bounds small-test.c:18: warning: array subscript is above array bounds small-test.c:18: warning: array subscript is above array bounds small-test.c:18: warning: 'u' is used uninitialized in this function 4.3 doesn't warn at all. Confirmed. I'd close it as fixed in 4.6 and add a testcase (no time for that right now). No warnings with recent versions. Given that resolving as fixed (also as per comment #4). |