Функция strcat по-прежнему работает, когда массив строк назначения слишком мал - PullRequest
0 голосов
/ 05 апреля 2020

Я должен воссоздать кучу строковых функций для домашней работы.

#include <stdio.h>
#include <string.h>
char *strcat1(char *s1, const char *s2);
int main(void)
{
    char string[4] = "asd";
    char string1[4] = "asd";
    char string2[] = "teststring";
    printf("%s\n", strcat(string, string2));
    printf("%s\n", strcat1(string1, string2));
}
char *strcat1(char *s1, const char *s2)
{
    size_t a=0;
    for(a;s1[a]!='\0';a++)
    {
    }
    size_t b=0;
    for(b;s2[b]!='\0';a++,b++)
    {
        s1[a]=s2[b];
    }
    s1[a]=s2[b];
    return s1;
}

вывод:

asdteststring
asdteststring

string и string1 может содержать 3 символа + \ 0, поэтому после a в s1[a] проходах 3 не должно ли это произойти? Почему это все еще работает? Я сталкивался с тем же самым при воссоздании strcpy.

1 Ответ

0 голосов
/ 05 апреля 2020

Ваш код демонстрирует неопределенное поведение (UB) , потому что, как вы говорите, целевой буфер недостаточно велик для хранения строки. Поэтому вы не удовлетворяете требованиям используемой библиотечной функции. UB не означает, что программа обязательно аварийно завершает работу, это означает, что она может cra sh.

Причина, по которой этого не происходит в этом случае, заключается в том, что выделенный вами буфер находится на части памяти, которая организована как стек. Следовательно, память за концом буфера существует. Он просто не принадлежит той переменной, к которой, как вы думаете, он принадлежит.


Фактически, если вы компилируете свою программу с -fsanitize=address, вы увидите, что strcat фактически вызывает переполнение буфера:

=================================================================
==16978==ERROR: AddressSanitizer: stack-buffer-overflow on address 0x7ffd3f946594 at pc 0x7ff2aec575f3 bp 0x7ffd3f946560 sp 0x7ffd3f945d10
WRITE of size 11 at 0x7ffd3f946594 thread T0
    #0 0x7ff2aec575f2 in __interceptor_strcat (/usr/lib/x86_64-linux-gnu/libasan.so.5+0xa95f2)
    #1 0x5638a1480330 in main (/tmp/_/a.out+0x1330)
    #2 0x7ff2aea11e0a in __libc_start_main ../csu/libc-start.c:308
    #3 0x5638a14800f9 in _start (/tmp/_/a.out+0x10f9)

Address 0x7ffd3f946594 is located in stack of thread T0 at offset 36 in frame
    #0 0x5638a14801c4 in main (/tmp/_/a.out+0x11c4)

  This frame has 3 object(s):
    [32, 36) 'string' (line 6) <== Memory access at offset 36 overflows this variable
    [48, 52) 'string1' (line 7)
    [64, 75) 'string2' (line 8)

Итак, после этой диагностики c, если я напечатаю string, я получу это:

eststring
Ошибка сегментации

Хотя string все равно должно быть asd.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...