LINUX.ORG.RU

Баг в libc или я не умею читать стандарт???

 , ,


1

3

Найден одним из новичков cyberforum. Ковыряем потихоньку. Всё ведёт к кривой реализации libio, показывая, что setlocale нипричём. Кстати, без setlocale баг не воспроизводится. Может кто-нибудь знает в чём дело???

[faust@archlinux РАзная всячина]$ cat 1.c && gcc 1.c && ./a.out
#include <string.h>
#include <errno.h>
#include <locale.h>
#include <stdio.h>
#include <wchar.h>

int main()
{
    
    setlocale(LC_ALL, "ru_RU.UTF-8"); /*а вот тут уже до лампочки 
        обращения setlocale к потоку stdin - он уже "широкий" и сегфолтов/стеков уже не будет*/
/*    printf("1. errno = %s\n", strerror(errno));*/

    getwc(stdin);

/*    printf("2. errno = %s\n", strerror(errno));*/
    return 0;
}
1111111111111111111111111
*** stack smashing detected ***: <unknown> terminated
Аварийный останов (стек памяти сброшен на диск)
[faust@archlinux РАзная всячина]$ cat 1.c && clang 1.c && ./a.out
#include <string.h>
#include <errno.h>
#include <locale.h>
#include <stdio.h>
#include <wchar.h>

int main()
{
    
    setlocale(LC_ALL, "ru_RU.UTF-8"); /*а вот тут уже до лампочки 
        обращения setlocale к потоку stdin - он уже "широкий" и сегфолтов/стеков уже не будет*/
/*    printf("1. errno = %s\n", strerror(errno));*/

    getwc(stdin);

/*    printf("2. errno = %s\n", strerror(errno));*/
    return 0;
}
111111111111111111111111
*** stack smashing detected ***: <unknown> terminated
Аварийный останов (стек памяти сброшен на диск)
[faust@archlinux РАзная всячина]$
★★★★★

Не воспроизводится, Arch Linux 64-bit.

Сделай

./gdb a.out
r
111111111111111111111111
bt

Посмотри, где там что.

EXL ★★★★★ ()

Похоже на баг в локалях glibc, надо проверить на musl или ещё чём-нибудь.

Bfgeshka ★★★★★ ()
Ответ на: комментарий от Bfgeshka

Хмм:

$ /lib64/libc.so.6 -v
GNU C Library (GNU libc) stable release version 2.28.
Copyright (C) 2018 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.
There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A
PARTICULAR PURPOSE.
Compiled by GNU CC version 8.2.0.
libc ABIs: UNIQUE IFUNC ABSOLUTE
EXL ★★★★★ ()

Как-то обсуждалось подобное поведение тут: glib-2.22 segfault после main (комментарий)

У меня с glibc 2.23 оба падения воспроизводятся.

7.21.2
[...]
5 Byte input/output functions shall not be applied to a
wide-oriented stream and wide character input/output functions shall not
be applied to a byte-oriented stream. [...]
4
[...]
2 If a “shall” or “shall not” requirement that appears outside of
a constraint or runtime-constraint is violated, the behavior is undefined. [...]

И я так понимаю, это было определение вне «constraint».

xaizek ★★★★★ ()
Ответ на: комментарий от EXL
(gdb) bt
#0  0x00007ffff7de7d7f in raise () from /usr/lib/libc.so.6
#1  0x00007ffff7dd2672 in abort () from /usr/lib/libc.so.6
#2  0x00007ffff7e2a878 in __libc_message () from /usr/lib/libc.so.6
#3  0x00007ffff7ebd415 in __fortify_fail_abort () from /usr/lib/libc.so.6
#4  0x00007ffff7ebd3c6 in __stack_chk_fail () from /usr/lib/libc.so.6
#5  0x00007ffff7e282dc in do_length () from /usr/lib/libc.so.6
Backtrace stopped: previous frame inner to this frame (corrupt stack?)
(gdb)
[faust@archlinux РАзная всячина]$ uname -ar
Linux archlinux 4.19.8-arch1-1-ARCH #1 SMP PREEMPT Sat Dec 8 13:49:11 UTC 2018 x86_64 GNU/Linux
[faust@archlinux РАзная всячина]$ 

Пробую разные варианты. Баг вылетает при закрытии потока на «посткоде» main() - то сегфолт, то стек - очень сильно похоже на выход за пределы в iconv, которую и использует setlocale...

Хотя может и не туда копаю. libio слишком уж для меня упутана.

/lib64/libc.so.6 -v
GNU C Library (GNU libc) stable release version 2.28.
Copyright (C) 2018 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.
There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A
PARTICULAR PURPOSE.
Compiled by GNU CC version 8.2.1 20180831.
libc ABIs: UNIQUE IFUNC ABSOLUTE
For bug reporting instructions, please see:
<https://bugs.archlinux.org/>.
drfaust ★★★★★ ()
Последнее исправление: drfaust (всего исправлений: 1)

Windows 10 + gcc version 8.2.1 20181207 (Rev1, Built by MSYS2 project) - не воспроизводится

Mandjaro + gcc версия 8.2.1 20180831 (GCC) - не воспроизводится

/lib64/libc.so.6 -v
GNU C Library (GNU libc) stable release version 2.28.
Copyright (C) 2018 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.
There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A
PARTICULAR PURPOSE.
Compiled by GNU CC version 8.2.1 20180831.
libc ABIs: UNIQUE IFUNC ABSOLUTE
For bug reporting instructions, please see:
<https://bugs.archlinux.org/>.
fsb4000 ★★★★★ ()
Ответ на: комментарий от drfaust

Что меня больше всего удивляет, коду более 15 лет и я не смог нагуглить ни одного упоминания о проблеме.

Кинь линк там ему этот: glib-2.22 segfault после main

EXL ★★★★★ ()

Воспроизводится на Fedora 29 x86_64, если собрать 32-разрядный бинарник. С 64-разрядным не воспроизводится. glibc 2.28. Похоже на баг.

Deleted ()
Ответ на: комментарий от xaizek

Если добавить явный вызов fwide() перед fgetwc(), который проходит успешно:

printf("fwide() == %d\n", fwide(stdin, 1));
То всё равно падает.

Кстати, падает только если на stdin подать больше трёх символов.

(gdb) r
Starting program: /home/im/projects/test/widecharcrash/test 
fwide() == 1
xxxx

Program received signal SIGSEGV, Segmentation fault.
0xf7e62db1 in do_length () from /lib/libc.so.6
(gdb) bt
#0  0xf7e62db1 in do_length () from /lib/libc.so.6
#1  0xf7e62840 in _IO_wfile_sync () from /lib/libc.so.6
#2  0xf7e6a0fa in _IO_default_setbuf () from /lib/libc.so.6
#3  0xf7e66926 in __GI__IO_file_setbuf () from /lib/libc.so.6
#4  0xf7e6ab64 in _IO_cleanup () from /lib/libc.so.6
#5  0xf7e234e2 in __run_exit_handlers () from /lib/libc.so.6
#6  0xf7e23527 in exit () from /lib/libc.so.6
#7  0xf7e0bc15 in __libc_start_main () from /lib/libc.so.6
#8  0x080490c6 in _start ()
Deleted ()
Ответ на: комментарий от Deleted

Да, я потом засомневался, учитывая что setlocale() не должен считаться за операцию ввода/вывода.

xaizek ★★★★★ ()
Ответ на: комментарий от Atlant

Кто хорошо владеет ангельским - оформите багтрэк. prik с кибера подтвердил, что это тот самый баг, про который говорил mironov_ivan:

По симптомам и трасам именно оно. Печально, что в багзиле баг открыт с 16го кода и авторам пох

drfaust ★★★★★ ()
15 мая 2019 г.
Ответ на: комментарий от drfaust

Урра. не прошло и полгода

Andreas Schwab Пофиксил баг в 2.30, после того как недавно ещё несколько подтверждений вылезло.

cvs-commit@gcc.gnu.org 2019-05-15 14:49:07 UTC The master branch has been updated by Andreas Schwab <schwab@sourceware.org>:

https://sourceware.org/git/gitweb.cgi?p=glibc.git;h=32ff397533715988c19cbf367...

commit 32ff397533715988c19cbf3675dcbd727ec13e18 Author: Andreas Schwab <schwab@suse.de> Date: Tue May 14 17:14:59 2019 +0200

Fix crash in _IO_wfile_sync (bug 20568) When computing the length of the converted part of the stdio buffer, use the number of consumed wide characters, not the (negative) distance to the end of the wide buffer.

drfaust ★★★★★ ()
Ответ на: комментарий от drfaust

Вот именно что, широкие символы это непереносимая параша пригодная только для нескольких языков.

anonymous ()
Ответ на: комментарий от anonymous

Ню-ню. Подсчитай кол-во русских и китайских символов в кошерном utf-8 тексте в той же линухе.

drfaust ★★★★★ ()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.