Bug 104009 - [12 Regression] r12-6030-g422f9eb7011b76c1 breaks kernel build
Summary: [12 Regression] r12-6030-g422f9eb7011b76c1 breaks kernel build
Status: RESOLVED FIXED
Alias: None
Product: gcc
Classification: Unclassified
Component: tree-optimization (show other bugs)
Version: 12.0
: P1 normal
Target Milestone: 12.0
Assignee: Siddhesh Poyarekar
URL:
Keywords: wrong-code
Depends on:
Blocks:
 
Reported: 2022-01-13 15:25 UTC by Siddhesh Poyarekar
Modified: 2023-12-14 03:10 UTC (History)
3 users (show)

See Also:
Host:
Target:
Build:
Known to work:
Known to fail:
Last reconfirmed: 2022-01-13 00:00:00


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Siddhesh Poyarekar 2022-01-13 15:25:45 UTC
Reproducer gleaned from the kernel:

const char *
nlmdbg_cookie2a(unsigned n, char **data)
{
  static char buf[255];
  unsigned int i, len = sizeof(buf);
  char *p = buf;

  len--;  /* allow for trailing \0 */
  for (i = 0 ; i < n ; i++)
    {
      if (len < 2)
	{
	  __builtin___strcpy_chk(p-3, "...", __builtin_object_size (p-3, 1));
	  break;
	}
      p += 2;
      len -= 2;
    }
  *p = '\0';

  return buf;
}

$ cat repr.c.031t.early_objsz 

;; Function nlmdbg_cookie2a (nlmdbg_cookie2a, funcdef_no=0, decl_uid=1980, cgraph_uid=1, symbol_order=0)

Computing maximum subobject size for _1:
Visiting use-def links for _1
Visiting use-def links for p_6
Visiting use-def links for p_9
Visiting use-def links for p_14
Found a dependency loop at p_6
Need to reexamine p_14
Need to reexamine p_6
Need to reexamine _1
Visiting use-def links for _1
Need to reexamine _1
Reexamining _1
Visiting use-def links for p_6
Need to reexamine p_6
Reexamining p_6
Visiting use-def links for p_14
Need to reexamine p_14
Reexamining p_14
_1: maximum subobject size 0
p_6: maximum subobject size 255
p_9: maximum subobject size 255
p_14: maximum subobject size 253
const char * nlmdbg_cookie2a (unsigned int n, char * * data)
{
  char * p;
  unsigned int len;
  unsigned int i;
  static char buf[255];
  char * _1;
  long unsigned int _2;
  char * _3;
  const char * _19;
  long unsigned int _20;

  <bb 2> :
  len_8 = 255;
  p_9 = &buf;
  len_10 = len_8 + 4294967295;
  i_11 = 0;
  goto <bb 6>; [INV]

  <bb 3> :
  if (len_5 <= 1)
    goto <bb 4>; [INV]
  else
    goto <bb 5>; [INV]

  <bb 4> :
  _1 = p_6 + 18446744073709551613;
  _20 = __builtin_object_size (_1, 1);
  _2 = MIN_EXPR <_20, 0>;
  _3 = p_6 + 18446744073709551613;
  __builtin___memcpy_chk (_3, "...", 4, _2);
  goto <bb 7>; [INV]

  <bb 5> :
  p_14 = p_6 + 2;
  len_15 = len_5 + 4294967294;
  i_16 = i_4 + 1;

  <bb 6> :
  # i_4 = PHI <i_11(2), i_16(5)>
  # len_5 = PHI <len_10(2), len_15(5)>
  # p_6 = PHI <p_9(2), p_14(5)>
  if (i_4 < n_12(D))
    goto <bb 3>; [INV]
  else
    goto <bb 7>; [INV]

  <bb 7> :
  *p_6 = 0;
  _19 = &buf;
  return _19;

}


Basically since p_6 is an estimate (i.e. the wholesize) and not a precise value, negative offsets don't quite work.  I need to figure out a way to punt on negative offsets if we're using size estimates instead of precise sizes.  This means that it'll work for dynamic object sizes (because at the moment they're always precise expressions) but not always for static sizes.

Right now it breaks for dynamic object sizes too, but that's only because early_objsz treats __builtin_dynamic_object_size as __builtin_object_size to get an upper bound and ends up zeroing it.  So punting should fix that too.
Comment 1 Siddhesh Poyarekar 2022-01-13 15:26:35 UTC
Bumping to P1 since we want to be able to build the kernel with fortification.
Comment 2 Jakub Jelinek 2022-01-13 15:29:47 UTC
Well, it is a P1 just from being a regression from 11 on a primary or secondary platform (and even more so as it is wrong-code).
Comment 3 GCC Commits 2022-01-14 08:11:05 UTC
The master branch has been updated by Siddhesh Poyarekar <siddhesh@gcc.gnu.org>:

https://gcc.gnu.org/g:17df585a3a6a852c71883cc2ff40e111a6875149

commit r12-6568-g17df585a3a6a852c71883cc2ff40e111a6875149
Author: Siddhesh Poyarekar <siddhesh@gotplt.org>
Date:   Fri Jan 14 08:56:15 2022 +0530

    tree-optimization/104009: Conservative underflow estimate in object size
    
    Restrict negative offset computation only to dynamic object sizes, where
    size expressions are accurate and not a maximum/minimum estimate and in
    cases where negative offsets definitely mean an underflow, e.g. in
    MEM_REF of the whole object with negative ofset in addr_object_size.
    
    This ends up missing some cases where __builtin_object_size could have
    come up with more precise results, so tests have been adjusted to
    reflect that.
    
    gcc/ChangeLog:
    
            PR tree-optimization/104009
            * tree-object-size.c (compute_builtin_object_size): Bail out on
            negative offset.
            (plus_stmt_object_size): Return maximum of wholesize and minimum
            of 0 for negative offset.
    
    gcc/testsuite/ChangeLog:
    
            PR tree-optimization/104009
            * gcc.dg/builtin-object-size-1.c (test10): New test.
            * gcc.dg/builtin-object-size-3.c (test10): Likewise.
            (test9): Expect zero size for negative offsets.
            * gcc.dg/builtin-object-size-4.c (test8): Likewise.
            * gcc.dg/builtin-object-size-5.c (test7): Drop test for
            __builtin_object_size.
    
    Signed-off-by: Siddhesh Poyarekar <siddhesh@gotplt.org>
Comment 4 Siddhesh Poyarekar 2022-01-14 08:12:49 UTC
I built a `make allyesconfig` kernel with this patch and trunk as of yesterday, so fixed.