[Bug 1956236] [NEW] wrong-code if stdcall is applied via template parameters

Kevin Puetz 1956236 at bugs.launchpad.net
Mon Jan 3 16:49:50 UTC 2022


Public bug reported:

g++ 9.3.0-17ubuntu1~20.04 miscompiles the following example for x86
(bar_stdcall should pop 4 bytes fewer than an bar_cdecl, as stdcall is
callee-cleanup for the argument). To see it in this minimized example
one must use `-O0` as it will otherwise be inlined and the calling-
convention will no longer be meaningful. Larger examples it can hit with
optimizations on.

>>>>>>>>>>>>>>>

// g++-9 -c -O0 simple.cpp -m32
//
// objdump -S simple.o

template<bool bIsStdcall, typename T> struct func_ptr_t;

template<typename T> struct func_ptr_t<false,T> {
	using type = void(*)(T);
};

template<typename T> struct func_ptr_t<true,T> {
#if 1
	using type = void(__attribute__((__stdcall__))*)(T);
#else
	using type = void(__attribute__((__stdcall__))*)(int); // this works, using T is important somehow
#endif
};

#if 1
	using foo_stdcall_ptr = func_ptr_t<true,int>::type;
	using foo_cdecl_ptr = func_ptr_t<false,int>::type;
#else
	using foo_stdcall_ptr = void(__attribute__((__stdcall__))*)(int,int);
	using foo_cdecl_ptr = void(*)(int,int);
#endif

foo_stdcall_ptr foo_stdcall;
foo_cdecl_ptr foo_cdecl;

void bar_stdcall() {
	foo_stdcall(1);
}

void bar_cdecl() {
	foo_cdecl(1);
}

>>>>>>>>>>>>>>>

--- bar_cdecl.S	2021-03-09 00:54:58.404022904 +0000
+++ bar_stdcall.S	2021-03-09 00:52:07.900015002 +0000
@@ -1,15 +1,15 @@
-<bar_cdecl()>:
+<bar_stdcall()>:
    0:	f3 0f 1e fb          	endbr32 
    4:	55                   	push   %ebp
    5:	89 e5                	mov    %esp,%ebp
    7:	83 ec 08             	sub    $0x8,%esp
-   a:	e8 fc ff ff ff       	call   32 <bar_cdecl()+0xb>
+   a:	e8 fc ff ff ff       	call   b <bar_stdcall()+0xb>
    f:	05 01 00 00 00       	add    $0x1,%eax
   14:	8b 80 00 00 00 00    	mov    0x0(%eax),%eax
   1a:	83 ec 0c             	sub    $0xc,%esp
   1d:	6a 01                	push   $0x1
   1f:	ff d0                	call   *%eax
-  21:	83 c4 10             	add    $0x10,%esp
+  21:	83 c4 0c             	add    $0xc,%esp
   24:	90                   	nop
   25:	c9                   	leave  
   26:	c3                   	ret    
```

Upstream gcc-9.3.0 does not have this bug (See
https://godbolt.org/z/vK3TdM318), but 9.4.0, 10.0, and 10.1 do). The
regression seems to have happened upstream in
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=90750 -
https://gcc.gnu.org/git/?p=gcc.git;a=commit;h=aa988998be8f85334665a6b049d5d9139408c250
- which ubuntu has backported into git-updates.patch (it's in in
gcc-9_9.3.0-17ubuntu1~20.04.debian.tar.xz, I have not pinned down when
ubuntu picked this up). The regression was fixed in 10.2 by
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=95222 -
https://gcc.gnu.org/git/?p=gcc.git;a=commit;efdbd4fbea08005091e490ec3f9972aa9c946374
and
https://gcc.gnu.org/git/?p=gcc.git;a=commit;0c473d8f32510fcc96d584ee5099b856cfd3d8d6).

I don't think it was realized (when the was found/fixed upstream) that
it could also cause wrong-code, so I'm just posting this to make you
aware that ubuntu has backported a regression and not the fix. I assume
you'll want to align with upstream on whether gcc-9 branch ends up
getting this fixed or not.

** Affects: gcc-9 (Ubuntu)
     Importance: Undecided
         Status: New

-- 
You received this bug notification because you are a member of Ubuntu
Foundations Bugs, which is subscribed to gcc-9 in Ubuntu.
https://bugs.launchpad.net/bugs/1956236

Title:
  wrong-code if stdcall is applied via template parameters

Status in gcc-9 package in Ubuntu:
  New

Bug description:
  g++ 9.3.0-17ubuntu1~20.04 miscompiles the following example for x86
  (bar_stdcall should pop 4 bytes fewer than an bar_cdecl, as stdcall is
  callee-cleanup for the argument). To see it in this minimized example
  one must use `-O0` as it will otherwise be inlined and the calling-
  convention will no longer be meaningful. Larger examples it can hit
  with optimizations on.

  >>>>>>>>>>>>>>>

  // g++-9 -c -O0 simple.cpp -m32
  //
  // objdump -S simple.o

  template<bool bIsStdcall, typename T> struct func_ptr_t;

  template<typename T> struct func_ptr_t<false,T> {
  	using type = void(*)(T);
  };

  template<typename T> struct func_ptr_t<true,T> {
  #if 1
  	using type = void(__attribute__((__stdcall__))*)(T);
  #else
  	using type = void(__attribute__((__stdcall__))*)(int); // this works, using T is important somehow
  #endif
  };

  #if 1
  	using foo_stdcall_ptr = func_ptr_t<true,int>::type;
  	using foo_cdecl_ptr = func_ptr_t<false,int>::type;
  #else
  	using foo_stdcall_ptr = void(__attribute__((__stdcall__))*)(int,int);
  	using foo_cdecl_ptr = void(*)(int,int);
  #endif

  foo_stdcall_ptr foo_stdcall;
  foo_cdecl_ptr foo_cdecl;

  void bar_stdcall() {
  	foo_stdcall(1);
  }

  void bar_cdecl() {
  	foo_cdecl(1);
  }

  >>>>>>>>>>>>>>>

  --- bar_cdecl.S	2021-03-09 00:54:58.404022904 +0000
  +++ bar_stdcall.S	2021-03-09 00:52:07.900015002 +0000
  @@ -1,15 +1,15 @@
  -<bar_cdecl()>:
  +<bar_stdcall()>:
      0:	f3 0f 1e fb          	endbr32 
      4:	55                   	push   %ebp
      5:	89 e5                	mov    %esp,%ebp
      7:	83 ec 08             	sub    $0x8,%esp
  -   a:	e8 fc ff ff ff       	call   32 <bar_cdecl()+0xb>
  +   a:	e8 fc ff ff ff       	call   b <bar_stdcall()+0xb>
      f:	05 01 00 00 00       	add    $0x1,%eax
     14:	8b 80 00 00 00 00    	mov    0x0(%eax),%eax
     1a:	83 ec 0c             	sub    $0xc,%esp
     1d:	6a 01                	push   $0x1
     1f:	ff d0                	call   *%eax
  -  21:	83 c4 10             	add    $0x10,%esp
  +  21:	83 c4 0c             	add    $0xc,%esp
     24:	90                   	nop
     25:	c9                   	leave  
     26:	c3                   	ret    
  ```

  Upstream gcc-9.3.0 does not have this bug (See
  https://godbolt.org/z/vK3TdM318), but 9.4.0, 10.0, and 10.1 do). The
  regression seems to have happened upstream in
  https://gcc.gnu.org/bugzilla/show_bug.cgi?id=90750 -
  https://gcc.gnu.org/git/?p=gcc.git;a=commit;h=aa988998be8f85334665a6b049d5d9139408c250
  - which ubuntu has backported into git-updates.patch (it's in in
  gcc-9_9.3.0-17ubuntu1~20.04.debian.tar.xz, I have not pinned down when
  ubuntu picked this up). The regression was fixed in 10.2 by
  https://gcc.gnu.org/bugzilla/show_bug.cgi?id=95222 -
  https://gcc.gnu.org/git/?p=gcc.git;a=commit;efdbd4fbea08005091e490ec3f9972aa9c946374
  and
  https://gcc.gnu.org/git/?p=gcc.git;a=commit;0c473d8f32510fcc96d584ee5099b856cfd3d8d6).

  I don't think it was realized (when the was found/fixed upstream) that
  it could also cause wrong-code, so I'm just posting this to make you
  aware that ubuntu has backported a regression and not the fix. I
  assume you'll want to align with upstream on whether gcc-9 branch ends
  up getting this fixed or not.

To manage notifications about this bug go to:
https://bugs.launchpad.net/ubuntu/+source/gcc-9/+bug/1956236/+subscriptions




More information about the foundations-bugs mailing list