当 char *buf 大于 read 系统调用的 size_t 计数时,为什么 shell 会运行剩余输入?

问题描述 投票:0回答:1

我在 Linux 机器上的 x86-64 程序集中遇到了一个小错误或意外行为。

.bss
部分,我在内存中保留了16个字节,我称之为
name

当用户输入他们的名字时,它将通过一条问候消息输出回屏幕上。但是,当用户输入大于 16 个字符的内容时,其余字符将立即在控制台中运行。 问题

这就是人们所说的缓冲区溢出吗? 但是为什么首先运行的是16个字符之后的代码?我认为该应用程序会崩溃或根本无法工作。消息的其余部分保存在哪里?我的 shell(即 zsh)如何运行特别是该代码?

如果这些问题听起来很愚蠢,我很抱歉,但我昨天才开始使用汇编语言,我试图了解 Linux 内核在做什么。


我的程序的完整源代码是这样的:

section .data
    question1   db "What is your name? "
    greeting    db "Hello, "

section .bss
    name        resb 16     ; Reserve 16 bytes in memory for "name"

section .text
    global _start           ; define at which label (address) the main program routine should start

_start:
    call _printQuestion
    call _getName
    call _printGreeting
    call _printName
    
    ; Define the next syscall to end the program
    mov     rax, 60         ; ID for sys_exit syscall
    mov     rdi, 0          ; rdi = errorcode value. 0 = No error
    syscall             ; run the syscall to exit

_getName:
    mov     rax, 0          ; Syscall 0 for sys_read
    mov rdi, 0          ; Standard Input
    mov rsi, name       
    mov rdx, 16
    syscall
    ret

_printQuestion:
    mov     rax, 1
    mov rdi, 1
    mov rsi, question1
    mov rdx, 19
    syscall
    ret

_printGreeting:
    mov     rax, 1
    mov rdi, 1
    mov rsi, greeting
    mov     rdx, 7
    syscall
    ret

_printName:
    mov rax, 1
    mov rdi, 1
    mov rsi, name
    mov rdx, 16
    syscall
    ret

我知道该程序会做意想不到的事情,但我没想到会发生这种情况,我想了解这是否是一个常见问题以及如何解决它。

linux assembly terminal x86-64 tty
1个回答
4
投票

发生这种情况是因为您的程序不一定读取整行输入。如果用户输入的行长度超过 16 个字符,您将读取其中的前 16 个字符。其余的保留在终端驱动程序的缓冲区中,并将在下次调用

read()
时返回。当程序退出时,shell 调用
read()
来获取下一个命令行,这将返回输入行的其余部分,然后 shell 执行它。

© www.soinside.com 2019 - 2024. All rights reserved.