<?xml version="1.0" encoding="UTF-8" ?>

<bugzilla version="5.2"
          urlbase="https://bugzilla.altlinux.org/"
          
          maintainer="jenya@basealt.ru"
>

    <bug>
          <bug_id>36038</bug_id>
          
          <creation_ts>2019-02-04 18:39:29 +0300</creation_ts>
          <short_desc>gcc8-c++ miscompiles functions returning non-void without return statements</short_desc>
          <delta_ts>2019-02-12 13:59:25 +0300</delta_ts>
          <reporter_accessible>1</reporter_accessible>
          <cclist_accessible>1</cclist_accessible>
          <classification_id>4</classification_id>
          <classification>Development</classification>
          <product>Sisyphus</product>
          <component>gcc8-c++</component>
          <version>unstable</version>
          <rep_platform>all</rep_platform>
          <op_sys>Linux</op_sys>
          <bug_status>CLOSED</bug_status>
          <resolution>FIXED</resolution>
          
          
          <bug_file_loc>https://gcc.gnu.org/bugzilla/show_bug.cgi?id=89218</bug_file_loc>
          <status_whiteboard></status_whiteboard>
          <keywords></keywords>
          <priority>P3</priority>
          <bug_severity>normal</bug_severity>
          <target_milestone>---</target_milestone>
          
          
          <everconfirmed>1</everconfirmed>
          <reporter name="Aleksei Nikiforov">darktemplaralt</reporter>
          <assigned_to name="Gleb F-Malinovskiy">glebfm</assigned_to>
          <cc>aen</cc>
    
    <cc>glebfm</cc>
    
    <cc>iv</cc>
    
    <cc>lav</cc>
    
    <cc>rider</cc>
    
    <cc>zerg</cc>
          
          <qa_contact>qa-sisyphus</qa_contact>

      

      

      

          <comment_sort_order>oldest_to_newest</comment_sort_order>  
          <long_desc isprivate="0" >
    <commentid>178147</commentid>
    <comment_count>0</comment_count>
    <who name="Aleksei Nikiforov">darktemplaralt</who>
    <bug_when>2019-02-04 18:39:29 +0300</bug_when>
    <thetext>Если есть функция, возвращающая bool, но в данной функции нет ни одного return, то при использовании gcc8-c++ генерируется очень странный ассемблерный код.

Есть два примера: synaptic и packagekit.

synaptic:

http://git.altlinux.org/gears/s/synaptic.git?p=synaptic.git;a=blob;f=synaptic/gtk/rguserdialog.cc;h=83349c1e64c61013dac72fe293a8055d84558b36;hb=cfd2d6d12072ecb8bd1c38cdd1cdf39c71e1ba28#l211

Функция bool RGGladeUserDialog::init(const char *name).

При сборке с gcc8-c++ генерируется ассемблерный код, в котором в конце функции стоит jump в середину функции. При продолжении выполнения данной функции после этого прыжка в итоге второй раз вызывается g_free(filename) и приложение падает.

Имеется уже закрытый соответствующий баг:
https://bugzilla.altlinux.org/show_bug.cgi?id=35725

Воспроизведение: пересобрать synaptic без патча synaptic-0.58-alt-gcc8-crash-fix.patch (либо взять версию 0.58-alt17) и запустить, приложение падает. Если же не падает, то открыть пункт меню &quot;Справка&quot; -&gt; &quot;Краткое описание&quot;.

packagekit:

http://git.altlinux.org/gears/p/packagekit.git?p=packagekit.git;a=blob;f=backends/aptcc/apt-messages.cpp;h=38c58b16b9907dcbeee318fc4618ea7b1496d119;hb=8a5988e96d431b69b98efd438b289e0a7664ab71#l32

Функция bool show_errors(PkBackendJob *job, PkErrorEnum errorCode, bool errModify).

В данном случае падает в выражении errors.str().empty() на строке 55.

Воспроизведение: взять packagekit версии 1.1.12-alt4, машину с Sisyphus, которую не обновляли несколько дней, запустить apt-get update, apt-get dist-upgrade в одном терминале, дождаться пока apt-get запросит подтверждение на обновление. Во втором терминале запустить pkcon update и дождаться запроса на подтверждение обновления. После этого в первом терминале подтвердить обновление через apt-get dist-upgrade, и когда оно начнётся - подтвердить во втором терминале обновление через pkcon update. Если dist-upgrade будет проходить достаточно долго (более 10 секунд), то обновление через pkcon update не сможет получить нужные локи, получит timeout и попытается сообщить соответствующую ошибку, и упадёт пытаясь это сделать.

Если изменить возвращаемый тип на void в этой функции, то проблема пропадает.

В обоих случаях gcc8-c++ выдаёт предупреждение:
apt-messages.cpp: In function &apos;bool show_errors(PkBackendJob*, PkErrorEnum, bool)&apos;:
apt-messages.cpp:61:1: warning: no return statement in function returning non-void [-Wreturn-type]
 }

Однако, несмотря на предупреждение, сборка заканчивается &quot;успешно&quot;, но сгенерирован неправильный код, который может неприятно удивить в рантайме.

Как минимум для synaptic при использовании gcc7-c++ такой проблемы замечено не было. Я считаю, что gcc8-c++ должен либо генерировать код, аналогичный более старым версиям gcc, либо должен выдавать ошибки, а не предупреждения, вместо генерации &quot;сюрпризов&quot;.</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>178152</commentid>
    <comment_count>1</comment_count>
    <who name="Dmitry V. Levin">ldv</who>
    <bug_when>2019-02-04 22:30:24 +0300</bug_when>
    <thetext>(In reply to comment #0)
&gt; Я считаю, что gcc8-c++ должен либо генерировать код, аналогичный более
&gt; старым версиям gcc, либо должен выдавать ошибки, а не предупреждения, вместо
&gt; генерации &quot;сюрпризов&quot;.

Было бы неплохо, но поскольку это UB, компилятор вправе делать всё что угодно.</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>178166</commentid>
    <comment_count>2</comment_count>
    <who name="Aleksei Nikiforov">darktemplaralt</who>
    <bug_when>2019-02-05 10:09:24 +0300</bug_when>
    <thetext>(В ответ на комментарий №1)
&gt; (In reply to comment #0)
&gt; &gt; Я считаю, что gcc8-c++ должен либо генерировать код, аналогичный более
&gt; &gt; старым версиям gcc, либо должен выдавать ошибки, а не предупреждения, вместо
&gt; &gt; генерации &quot;сюрпризов&quot;.
&gt; 
&gt; Было бы неплохо, но поскольку это UB, компилятор вправе делать всё что угодно.

Я как знал, что такой комментарий будет :)
Да, это скорее всего UB, но поведение g++-8 по сравнению с g++-7 - явная деградация.</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>178167</commentid>
    <comment_count>3</comment_count>
      <attachid>7988</attachid>
    <who name="Aleksei Nikiforov">darktemplaralt</who>
    <bug_when>2019-02-05 10:36:47 +0300</bug_when>
    <thetext>Created attachment 7988
gxx-bug-36038.cpp

Файл с примером, на котором g++ генерирует кривой код.

На машине x86_64 при использовании g++-7 -O2 генерируется нормальный код и получается следующий вывод:
Calling function
Running 1 time
Successfully returned from function

При использовании g++-8 -O0 внезапно тоже всё хорошо, аналогично прошлому случаю. Однако, при использовании g++-8 -O2 внезапно программа падает:
Calling function
Running 1 time
Ошибка сегментирования (стек памяти сброшен на диск)

Если посмотреть код функции somefunction, то при использовании g++-8 -O2 получается следующий код:
(gdb) $ disassemble  somefunction  
Dump of assembler code for function somefunction():
   0x00000000004011e0 &lt;+0&gt;:     sub    $0x8,%rsp
   0x00000000004011e4 &lt;+4&gt;:     mov    $0x1,%edx
   0x00000000004011e9 &lt;+9&gt;:     mov    $0x402010,%esi
   0x00000000004011ee &lt;+14&gt;:    xor    %eax,%eax
   0x00000000004011f0 &lt;+16&gt;:    mov    $0x1,%edi
   0x00000000004011f5 &lt;+21&gt;:    callq  0x401030 &lt;__printf_chk@plt&gt;

Даже никакого ret нет, неудивительно что падает. В других вариантах (с g++-7 или с -O0) код функции намного длиннее и содержит retq.</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>178168</commentid>
    <comment_count>4</comment_count>
    <who name="Anton Farygin">rider</who>
    <bug_when>2019-02-05 10:40:03 +0300</bug_when>
    <thetext>Дим, а давай включим Werror для этого предупреждения и посмотрим что сломается при сборке ?</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>178184</commentid>
    <comment_count>5</comment_count>
    <who name="Dmitry V. Levin">ldv</who>
    <bug_when>2019-02-05 15:05:48 +0300</bug_when>
    <thetext>(In reply to comment #2)
&gt; (В ответ на комментарий №1)
&gt; &gt; (In reply to comment #0)
&gt; &gt; &gt; Я считаю, что gcc8-c++ должен либо генерировать код, аналогичный более
&gt; &gt; &gt; старым версиям gcc, либо должен выдавать ошибки, а не предупреждения, вместо
&gt; &gt; &gt; генерации &quot;сюрпризов&quot;.
&gt; &gt; 
&gt; &gt; Было бы неплохо, но поскольку это UB, компилятор вправе делать всё что угодно.
&gt; 
&gt; Я как знал, что такой комментарий будет :)
&gt; Да, это скорее всего UB, но поведение g++-8 по сравнению с g++-7 - явная
&gt; деградация.

Понятно же, почему так происходит: в gcc8 стало больше всяких оптимизаций, которые в случае UB делают фиг знает что.

(In reply to comment #4)
&gt; Дим, а давай включим Werror для этого предупреждения и посмотрим что сломается
&gt; при сборке ?

Было бы неплохо, но -Wreturn-type охватывает не только &quot;no return statement in function returning non-void&quot;, но и другие.

В нынешнем Сизифе &quot;no return statement in function returning non-void&quot; встречается в логе сборки 98 пакетов, а всего предупреждения от -Wreturn-type встречаются в логе сборки 277 пакетов.</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>178190</commentid>
    <comment_count>6</comment_count>
    <who name="Aleksei Nikiforov">darktemplaralt</who>
    <bug_when>2019-02-05 17:31:09 +0300</bug_when>
    <thetext>(В ответ на комментарий №5)
&gt; Было бы неплохо, но -Wreturn-type охватывает не только &quot;no return statement in
&gt; function returning non-void&quot;, но и другие.
&gt; 
&gt; В нынешнем Сизифе &quot;no return statement in function returning non-void&quot;
&gt; встречается в логе сборки 98 пакетов, а всего предупреждения от -Wreturn-type
&gt; встречаются в логе сборки 277 пакетов.

Я читаю это так: &quot;в Сизифе до 98 пакетов потенциально сломано, но пересобрать надо будет 277 пакетов&quot;.

Возможно не каждое предупреждение говорит о подобной ошибке. Вопрос в том, сколько из этих пакетов реально уже незаметно сломано с gсс8-с++ (как минимум 1 уже починен, ещё 1 известен), сколько сломается при первой же пересборке, и когда на эти проблемы кто-нибудь нарвётся. И хорошо, если проблема будет вылезать сразу в виде крэша. Два случая, что я видел, приводят к крэшу. Но можно представить сценарии и похуже, UB ведь.</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>178211</commentid>
    <comment_count>7</comment_count>
    <who name="Dmitry V. Levin">ldv</who>
    <bug_when>2019-02-06 04:37:03 +0300</bug_when>
    <thetext>(In reply to comment #6)
&gt; (В ответ на комментарий №5)
&gt; &gt; Было бы неплохо, но -Wreturn-type охватывает не только &quot;no return statement in
&gt; &gt; function returning non-void&quot;, но и другие.
&gt; &gt; 
&gt; &gt; В нынешнем Сизифе &quot;no return statement in function returning non-void&quot;
&gt; &gt; встречается в логе сборки 98 пакетов, а всего предупреждения от -Wreturn-type
&gt; &gt; встречаются в логе сборки 277 пакетов.
&gt; 
&gt; Я читаю это так: &quot;в Сизифе до 98 пакетов потенциально сломано, но пересобрать
&gt; надо будет 277 пакетов&quot;.

Можно сделать так, чтобы gcc и/или g++ генерили ошибку вместо предупреждения только для &quot;no return statement in function returning non-void&quot;.

Непонятно, сколько пакетов на самом деле потенциально сломано, и как пофиксить 98 пакетов.</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>178212</commentid>
    <comment_count>8</comment_count>
    <who name="Dmitry V. Levin">ldv</who>
    <bug_when>2019-02-06 05:24:29 +0300</bug_when>
    <thetext>Вот пример попроще:

static int foo(void)
{
}

int main(void)
{
    return foo();
}

gcc на нём делает обычный код:

main:
.LFB1:
	.cfi_startproc
	xorl	%eax, %eax
	ret
	.cfi_endproc

g++ на нём делает код, который падает:

main:
.LFB1:
	.cfi_startproc
	.cfi_endproc</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>178250</commentid>
    <comment_count>9</comment_count>
    <who name="Aleksei Nikiforov">darktemplaralt</who>
    <bug_when>2019-02-06 17:18:08 +0300</bug_when>
    <thetext>Нашёл соответствующий апстримный баг:

https://gcc.gnu.org/bugzilla/show_bug.cgi?id=87515

tl;dr: won&apos;t fix, используйте -Werror=return-type.</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>178271</commentid>
    <comment_count>10</comment_count>
    <who name="Dmitry V. Levin">ldv</who>
    <bug_when>2019-02-07 00:36:47 +0300</bug_when>
    <thetext>Upstream statement:

C++ says it is undefined even if you don&apos;t use the return value.  This is different from C.

GCC assumes that the path leading to the return without a value will not happen so it uses __builtin_unreachable call there.</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>178272</commentid>
    <comment_count>11</comment_count>
    <who name="Dmitry V. Levin">ldv</who>
    <bug_when>2019-02-07 00:40:00 +0300</bug_when>
    <thetext>В качестве решения предлагаю сделать &quot;no return statement in function returning non-void&quot; неотключаемой ошибкой в g++.</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>178291</commentid>
    <comment_count>12</comment_count>
    <who name="Anton Farygin">rider</who>
    <bug_when>2019-02-07 07:39:34 +0300</bug_when>
    <thetext>Давайте так и сделаем.</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>178297</commentid>
    <comment_count>13</comment_count>
    <who name="Aleksei Nikiforov">darktemplaralt</who>
    <bug_when>2019-02-07 10:25:36 +0300</bug_when>
    <thetext>Если починить g++ нельзя, то других вариантов не остаётся.</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>178308</commentid>
    <comment_count>14</comment_count>
    <who name="Dmitry V. Levin">ldv</who>
    <bug_when>2019-02-07 13:25:07 +0300</bug_when>
    <thetext>Как минимум, следующие 45 пакетов нуждаются в починке:

AlephOne-1.0.1-alt1.2
CGenius-1.9.9.6beta-alt1
OpenAD-20140315-alt4
antico-deluxe-0.1.96-alt1.2
arpage-0.3.3-alt3_24
bloboats-1.0.2-alt2
canorus-0.6svn-alt1.qa2
cooldown-24-alt1.1
duel3-0.1-alt3_0.24.20060225.qa1
extrema-4.4.5-alt2
fbg-0.9.1-alt3_12
fceux-2.2.3-alt1
freehdl-0.0.8-alt4
glob2-0.9.4.4-alt1.qa7.1
gnome-quod-0.2.3-alt2
imule-1.4.6-alt5
kbookocr-2.1.0-alt2
kismet-2014.02.R1-alt1
kumir-1.9.1.2810-alt2
lib2geom-20081103-alt1.5
libfreeimage-3.18.0-alt1
libplotmm-0.1.2-alt2
mapsoft-20180722-alt1
megafuse-1.0.0-alt3.3
mirall-1.0.2-alt5
nted-1.10.18-alt3
numptyphysics-0.3.160-alt1
openscada-0.9.0-alt2
packagekit-1.1.12-alt4
paris-traceroute-0.92-alt1
perl-JavaScript-V8-0.070-alt7.1
pfstools-2.1.0-alt3
printer-driver-splix-2.0.1-alt1.svn315
procbench-0.9.0a-alt3.1
qcat-0.5-alt5.1.qa1
qkismet-0.3.1-alt1.qa1
qt-fsarchiver-0.8.4.0-alt1
qtrainer-0.5.2-alt2.qa2
sprng-4.4-alt1
synaptic-0.58-alt20
verlihub-0.9.8e-alt2
verlihub-plugin-python-1.1-alt2.1.1.1
verlihub-plugins-0.1-alt2.qa2.1
verlihub-plugins-lua51-1.8.1-alt1.qa2
yaafe-0.64-alt2.git20130420</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>178347</commentid>
    <comment_count>15</comment_count>
    <who name="Dmitry V. Levin">ldv</who>
    <bug_when>2019-02-08 03:26:35 +0300</bug_when>
    <thetext>g++ -Wreturn-type генерит три вида ошибок:
1. no return statement in function returning non-void
2. control reaches end of non-void function
3. ISO C++ forbids declaration of &apos;main&apos; with no type

Первый вариант мы уже обсудили, в Сизифе таких пакетов на С++ минимум 45.

Второй вариант не намного лучше первого, g++ точно так же генерит __builtin_unreachable() в конце функции, после чего в результате оптимизации от такой функции мало чего остаётся.  В Сизифе таких пакетов на С++ минимум 60, из которых 25 уже проходят по первому варианту.

Третий вариант выглядит безобидно, в Сизифе таких пакетов 5, из которых 2 уже проходят по первому варианту.

Всего пакетов на С++, которые в результате включения -Werror=return-type в g++ перестанут собираться, как минимум 83.</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>178349</commentid>
    <comment_count>16</comment_count>
    <who name="Anton Farygin">rider</who>
    <bug_when>2019-02-08 07:40:12 +0300</bug_when>
    <thetext>Серёг, посмотри, как мы сможем помочь с исправлениями в этих пакетах ?</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>178358</commentid>
    <comment_count>17</comment_count>
    <who name="Sergey V Turchin">zerg</who>
    <bug_when>2019-02-08 11:00:16 +0300</bug_when>
    <thetext>(В ответ на комментарий №16)
&gt; Серёг, посмотри, как мы сможем помочь с исправлениями в этих пакетах ?
Да, всем сможем. Наверняка там в большинстве случаев в контекст не нужно особо вдаваться.</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>178391</commentid>
    <comment_count>18</comment_count>
    <who name="Dmitry V. Levin">ldv</who>
    <bug_when>2019-02-08 17:09:04 +0300</bug_when>
    <thetext>Я решил просто добавить -Werror=return-type в g++ и не делать ошибку неотключаемой, поскольку в теории g++ может не увидеть, что из функции, в которой реализуется первый или второй вариант -Wreturn-type, на самом деле есть выход через какую-нибудь неразмеченную noreturn- или throw-функцию.</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>178404</commentid>
    <comment_count>19</comment_count>
    <who name="Anton Farygin">rider</who>
    <bug_when>2019-02-09 08:50:01 +0300</bug_when>
    <thetext>отличное сбалансированное решение.
Может быть, перед или после выкладывания стоит рассказать об этой проблеме в рассылке (как и о стандартных способах починки) ?</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>178408</commentid>
    <comment_count>20</comment_count>
    <who name="Repository Robot">repository-robot</who>
    <bug_when>2019-02-09 12:24:34 +0300</bug_when>
    <thetext>gcc8-8.2.1-alt4 -&gt; sisyphus:

Thu Feb 07 2019 Dmitry V. Levin &lt;ldv@altlinux&gt; 8.2.1-alt4
- Added ppc64le support (by glebfm@).
- Fixed profiledbootstrap build (by glebfm@).
- g++: enabled -Werror=return-type by default (closes: #36038).
- libcc1.so.0: cleaned up using a fixed libtool (closes: #36045).</thetext>
  </long_desc>
      
          <attachment
              isobsolete="0"
              ispatch="0"
              isprivate="0"
          >
            <attachid>7988</attachid>
            <date>2019-02-05 10:36:47 +0300</date>
            <delta_ts>2019-02-05 10:36:47 +0300</delta_ts>
            <desc>gxx-bug-36038.cpp</desc>
            <filename>gxx-bug-36038.cpp</filename>
            <type>text/x-c++src</type>
            <size>441</size>
            <attacher name="Aleksei Nikiforov">darktemplaralt</attacher>
            
              <data encoding="base64">I2luY2x1ZGUgPHN0ZGlvLmg+CiNpbmNsdWRlIDxzdGRleGNlcHQ+Cgpib29sIHNvbWVmdW5jdGlv
bigpCnsKCWludCBpID0gMDsKCglwcmludGYoIlJ1bm5pbmcgJWQgdGltZVxuIiwgKytpKTsKCglp
ZiAoaSA+IDEpCgl7CgkJdGhyb3cgc3RkOjpydW50aW1lX2Vycm9yKCJUaGlzIGNvZGUgc2hvdWxk
IGJlIHVucmVhY2hhYmxlIik7Cgl9Cn0KCmludCBtYWluKGludCBhcmdjLCBjaGFyICoqYXJndikK
ewoJdHJ5Cgl7CgkJcHJpbnRmKCJDYWxsaW5nIGZ1bmN0aW9uXG4iKTsKCQlzb21lZnVuY3Rpb24o
KTsKCQlwcmludGYoIlN1Y2Nlc3NmdWxseSByZXR1cm5lZCBmcm9tIGZ1bmN0aW9uXG4iKTsKCX0K
CWNhdGNoIChjb25zdCBzdGQ6OmV4Y2VwdGlvbiAmZSkKCXsKCQlwcmludGYoIkNhdWdodCBleGNl
cHRpb246ICVzXG4iLCBlLndoYXQoKSk7Cgl9CgoJcmV0dXJuIDA7Cn0K
</data>

          </attachment>
      

    </bug>

</bugzilla>