LINUX.ORG.RU

glib-2.22 segfault после main

 ,


0

1

От чего может быть сегфолт после main?

Например, в таком демонстрационном бесполезном куске кода, у меня программа падает, если дать ей на stdin больше 5 символов, если скомпилировать ее с glibc-2.22.

Если закрыть stdin, перед выходом из main, то сегфолта нет. С glibc-2.21 тоже не сегфолтится, даже если не закрывать stdin. Что-то поменялось в glibc-2.22, или это только у меня так?

#include <stdio.h>
#include <locale.h>
#include <wchar.h>

static const int N = 2;

int main(void) {
  setlocale(LC_ALL, "");
  wchar_t data[N];
  fgetws(data, N, stdin);
  printf("%ls\n", data);
  /* fclose(stdin); */
  return 0;
}

Ты про \0 на конце строки забыл. Соответственно у тебя строка не заканчивается после второго символа и printf идёт до тех пор пока не вылезет за пределы выделенной памяти.

wchar_t data[N+1] так сделай.

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

fgetws добавляет \0 вроде:

You must supply COUNT wide characters worth of space in WS, but the number of characters read is at most COUNT - 1. The extra character space is used to hold the null wide character at the end of the string

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

segfаult после после выхода из main

=> 0x000003fff7a5364c <+252>:	mov    %eax,%edi
   0x000003fff7a5364e <+254>:	callq  0x3fff7a69d10 <exit>
   0x000003fff7a53653 <+259>:	xor    %edx,%edx
   0x000003fff7a53655 <+261>:	jmpq   0x3fff7a53595 <__libc_start_main+69>
   0x000003fff7a5365a <+266>:	mov    0x38660f(%rip),%rax        # 0x3fff7dd9c70
   0x000003fff7a53661 <+273>:	ror    $0x11,%rax
   0x000003fff7a53665 <+277>:	xor    %fs:0x30,%rax
   0x000003fff7a5366e <+286>:	callq  *%rax
   0x000003fff7a53670 <+288>:	mov    0x3865e9(%rip),%rax        # 0x3fff7dd9c60
   0x000003fff7a53677 <+295>:	ror    $0x11,%rax
   0x000003fff7a5367b <+299>:	xor    %fs:0x30,%rax
   0x000003fff7a53684 <+308>:	lock decl (%rax)
   0x000003fff7a53687 <+311>:	sete   %dl
---Type <return> to continue, or q <return> to quit---
   0x000003fff7a5368a <+314>:	test   %dl,%dl
   0x000003fff7a5368c <+316>:	je     0x3fff7a536ae <__libc_start_main+350>
   0x000003fff7a5368e <+318>:	xor    %eax,%eax
   0x000003fff7a53690 <+320>:	jmp    0x3fff7a5364c <__libc_start_main+252>
   0x000003fff7a53692 <+322>:	mov    0x8(%rsp),%rax
   0x000003fff7a53697 <+327>:	lea    0x14b2f7(%rip),%rdi        # 0x3fff7b9e995
   0x000003fff7a5369e <+334>:	mov    (%rax),%rsi
   0x000003fff7a536a1 <+337>:	xor    %eax,%eax
   0x000003fff7a536a3 <+339>:	callq  *0xc8(%rdx)
   0x000003fff7a536a9 <+345>:	jmpq   0x3fff7a535c1 <__libc_start_main+113>
   0x000003fff7a536ae <+350>:	mov    $0x3c,%edx
   0x000003fff7a536b3 <+355>:	nopl   0x0(%rax,%rax,1)
   0x000003fff7a536b8 <+360>:	xor    %edi,%edi
   0x000003fff7a536ba <+362>:	mov    %edx,%eax
   0x000003fff7a536bc <+364>:	syscall 
   0x000003fff7a536be <+366>:	jmp    0x3fff7a536b8 <__libc_start_main+360>
   0x000003fff7a536c0 <+368>:	mov    0x8(%rsp),%rax
   0x000003fff7a536c5 <+373>:	mov    0x38078c(%rip),%rdx        # 0x3fff7dd3e58
   0x000003fff7a536cc <+380>:	lea    0x14b2dc(%rip),%rdi        # 0x3fff7b9e9af
   0x000003fff7a536d3 <+387>:	mov    (%rax),%rsi
   0x000003fff7a536d6 <+390>:	xor    %eax,%eax
   0x000003fff7a536d8 <+392>:	callq  *0xc8(%rdx)
   0x000003fff7a536de <+398>:	jmpq   0x3fff7a535fa <__libc_start_main+170>
   0x000003fff7a536e3 <+403>:	mov    0x118(%rax),%r13
   0x000003fff7a536ea <+410>:	mov    0x3806f7(%rip),%rax        # 0x3fff7dd3de8
   0x000003fff7a536f1 <+417>:	xor    %r12d,%r12d
   0x000003fff7a536f4 <+420>:	mov    (%rax),%rbp
   0x000003fff7a536f7 <+423>:	mov    0x18(%r13),%rax
   0x000003fff7a536fb <+427>:	test   %rax,%rax
   0x000003fff7a536fe <+430>:	je     0x3fff7a53710 <__libc_start_main+448>
   0x000003fff7a53700 <+432>:	mov    %r12d,%edi
   0x000003fff7a53703 <+435>:	add    $0x47,%rdi
   0x000003fff7a53707 <+439>:	shl    $0x4,%rdi
   0x000003fff7a5370b <+443>:	add    %rbp,%rdi
   0x000003fff7a5370e <+446>:	callq  *%rax
   0x000003fff7a53710 <+448>:	add    $0x1,%r12d
   0x000003fff7a53714 <+452>:	mov    0x40(%r13),%r13
   0x000003fff7a53718 <+456>:	cmp    %r12d,%r14d
   0x000003fff7a5371b <+459>:	jne    0x3fff7a536f7 <__libc_start_main+423>
   0x000003fff7a5371d <+461>:	jmpq   0x3fff7a535f2 <__libc_start_main+162>
End of assembler dump.
(gdb) ni
0x000003fff7a5364e in __libc_start_main () from /lib64/libc.so.6
(gdb) ni

Program received signal SIGSEGV, Segmentation fault.
0x000003fff7aa69bf in ?? () from /lib64/libc.so.6
(gdb) ni

Program terminated with signal SIGSEGV, Segmentation fault.
The program no longer exists.
trupanka
() автор топика
Ответ на: комментарий от trupanka

Может дело в <exit>? Я в ассемблер не умею, не понимаю что тут происходит

Вот нормальный выход с glib-2.21:

(gdb) disassemble 0x3fff7a68690
Dump of assembler code for function exit:
   0x000003fff7a68690 <+0>:     push   %rbp
   0x000003fff7a68691 <+1>:     mov    %rsp,%rbp
   0x000003fff7a68694 <+4>:     sub    $0x1020,%rsp
   0x000003fff7a6869b <+11>:    orq    $0x0,(%rsp)
   0x000003fff7a686a0 <+16>:    add    $0x1020,%rsp
   0x000003fff7a686a7 <+23>:    lea    0x36beca(%rip),%rsi        # 0x3fff7dd4578
   0x000003fff7a686ae <+30>:    mov    $0x1,%edx
   0x000003fff7a686b3 <+35>:    callq  0x3fff7a68550

А это с glibc-2.22:

(gdb) disassemble 0x3fff7a69d10
Dump of assembler code for function exit:
   0x000003fff7a69d10 <+0>:	sub    $0x1028,%rsp
   0x000003fff7a69d17 <+7>:	orq    $0x0,(%rsp)
   0x000003fff7a69d1c <+12>:	add    $0x1020,%rsp
   0x000003fff7a69d23 <+19>:	lea    0x36a84e(%rip),%rsi        # 0x3fff7dd4578
   0x000003fff7a69d2a <+26>:	mov    $0x1,%edx
   0x000003fff7a69d2f <+31>:	callq  0x3fff7a69be0

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

Воспроизводится, если вместо return 0 делать exit(0). Вот backtrace:

(gdb) bt
#0  0x00007ffff7a85be0 in do_length () from /lib64/libc.so.6
#1  0x00007ffff7a8560d in __GI__IO_wfile_sync () from /lib64/libc.so.6
#2  0x00007ffff7a8c2d7 in _IO_default_setbuf () from /lib64/libc.so.6
#3  0x00007ffff7a88d89 in __GI__IO_file_setbuf () from /lib64/libc.so.6
#4  0x00007ffff7a8cd91 in _IO_cleanup () from /lib64/libc.so.6
#5  0x00007ffff7a4857b in __run_exit_handlers () from /lib64/libc.so.6
#6  0x00007ffff7a48625 in exit () from /lib64/libc.so.6
#7  0x000000000040083a in main () at tst2.c:13
do_length() как-то затирает стек и всё падает при выходе из этой функции. Возможно, что это вина iconv, так как при определённой длине ввода можно получить:
a.out: ../iconv/skeleton.c:415: __gconv_transform_utf8_internal: Assertion `outbufstart == ((void *)0)' failed.
Может и нет. Я на Slackware, здесь никаких патчей для glibc быть не должно, так что похоже на их баг. В трекере похожего не вижу, но было бы хорошо проверить это ещё на мастере.

xaizek ★★★★★
()
Последнее исправление: xaizek (всего исправлений: 1)
Ответ на: комментарий от xaizek

Спасибо. Значит не только у меня. Осталось выяснить в чем же дело.

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