Break Infinite L oop После сигнала SIGSEVG - PullRequest
1 голос
/ 24 апреля 2020

Я пытаюсь найти максимальный размер стека с помощью моей программы. Я знаю, что в моей ОС максимальный размер стека равен 8 МБ. Поэтому я пытаюсь сделать бесконечным l oop, пока это не вызовет ошибку сегментации. Тогда мне нужно разбить это l oop, чтобы я мог рассчитать размер. Как я могу это сделать? Есть ли способ сломать бесконечное l oop после сигнала SIGSEGV?

 static void handler(int signo)
    {
        if(signo == SIGSEGV)
        {
            printf("Waoh, caught signal\n");
        }
    }

    int main()
    {
        int counter = 8964;
        stack_t sigstack;
        sigstack.ss_sp = malloc(SIGSTKSZ);
        if( sigstack.ss_sp == NULL)
        {
            printf("Err: malloc error\n");
            exit(EXIT_FAILURE);
        }
        sigstack.ss_size = SIGSTKSZ;
        sigstack.ss_flags = 0;

        if(sigaltstack(&sigstack, NULL) == -1)
        {
            printf("Err: sigaltstack error\n");
            exit(EXIT_FAILURE);
        }
        struct sigaction act;
        act.sa_flags = SA_ONSTACK;
        sigemptyset(&act.sa_mask);
        act.sa_handler = handler;
        sigaction(SIGSEGV, &act, NULL);

        do
        {
            char a[counter];
            counter += 8964;
        } while (1);

        return 0;
    }

1 Ответ

2 голосов
/ 24 апреля 2020

Я изменил вашу программу, чтобы вычислить оценку размера стека, а затем с помощью siglongjmp возвратился из обработчика сигнала в предположительно безопасное место в main непосредственно перед l oop, которое выделяет массив переменной длины. (Обратите внимание, что способ размещения массивов переменной длины зависит от компилятора, и не может быть безопасного способа возобновить выполнение в main после переполнения стека).

printf с в обработчике сигналов только для отладки; их можно удалить, не затрагивая остальную часть программы.

#include <stdio.h>
#include <stddef.h>
#include <stdlib.h>
#include <signal.h>
#include <setjmp.h>

ptrdiff_t s_size_computed;
void *s_base_estimated;
sigjmp_buf env;

void handler (int signo, siginfo_t *info, void *ucontext)
{
        printf("Caught signal %d\n", signo);
        if (signo == SIGSEGV)
        {
                printf("faulting address %p\n", info->si_addr);
                s_size_computed = (char *)s_base_estimated - (char *)info->si_addr;
                siglongjmp(env, 1);
        }
}

int main()
{
        int counter = 8964;
        stack_t sigstack;
        sigstack.ss_sp = malloc(SIGSTKSZ);
        if (sigstack.ss_sp == NULL)
        {
                printf("Err: malloc error\n");
                exit(EXIT_FAILURE);
        }
        sigstack.ss_size = SIGSTKSZ;
        sigstack.ss_flags = 0;

        if (sigaltstack(&sigstack, NULL) == -1)
        {
                printf("Err: sigaltstack error\n");
                exit(EXIT_FAILURE);
        }
        s_base_estimated = &counter;
        printf("&locals %p\n", s_base_estimated);
        struct sigaction act;
        act.sa_flags = SA_ONSTACK|SA_SIGINFO;
        sigemptyset(&act.sa_mask);
        act.sa_sigaction = handler;
        sigaction(SIGSEGV, &act, NULL);
        if (sigsetjmp(env, 0) == 1)
        {
                printf("computed stack size %td\n", s_size_computed);
                exit(1);
        }
        do
        {
                char a[counter];
                counter += 8964;
                a[0] = 0;         /* access element closest to top of stack (x86) */
        } while (1);

        return 0;
}

Вот вывод на моей системе Ubuntu:

mp:~$ ./stack
&locals 0x7fffeb60e0dc
Caught signal 11
faulting address 0x7fffeae0d960
computed stack size 8390524
mp:~$ ulimit -s
8192
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...