Хитрость, предотвращающая постоянную компиляцию выражения компилятором

У меня есть строковый литерал в моей программе, я пытаюсь создать любительскую контрольную сумму, чтобы гарантировать, что строковый литерал не был заменен в переносимом исполняемом файле.

Для этого я создаю хеш строкового литерала и сохраняю его как целочисленный литерал в программе. Теперь у меня есть два литерала, один для строки и один для хэша.

В моем коде я реализую контрольную сумму, используя функцию, которая хэширует строковый литерал таким же образом, я создаю новый хэш времени выполнения и проверяю этот хэш на хеш-литерал.

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

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

5

Решение

Возможно, вы объявите строковый литерал как const volatileнапример,

const volatile char myliteral[] = "some literal string";

и вы также можете вычислить хеш во время сборки, например, есть что-то в вашей процедуре сборки, чтобы извлечь соответствующие строки и отдельно вычислить хеш.

Наконец, если строка и ее хэш находятся в двух разных единицах перевода (например, в file1.c а также file2.c) вам нужна оптимизация во время компоновки, чтобы встраивание происходило во время сборки. С током НКУ (т.е. GCC 4.9 или 5) вам нужно эксплицитно проходить -flto во время компиляции и во время соединения, чтобы получить оптимизацию во время соединения, так что если вы этого не сделаете эксплицитно это (например, с CC=gcc -flto -O2 в вашем Makefile), этого не произойдет.

Кстати, вы можете проверить контрольную сумму всего исполняемого файла, или всей общей библиотеки, или некоторого заданного объектного файла. Детали зависят от ОС. По линуксу смотри dlopen (3), dlsym (3), dladdr (3), dl_iterate_phdr (5), Эльф (5), Proc (5)

Кроме того, вы могли бы хешировать некоторые случайная суффиксная подстрока исходного литерала (например, хеш myliteral+random()%strlen(myliteral) во время выполнения) и сохраните и сравните с постоянным массивом таких частичных хэшей. Компилятор вряд ли сможет встроить все это!

Я действительно считаю, что на практике это не является реальной проблемой: никто не будет заботиться о вашем исполняемом файле, и никто не потратит время на его декомпиляцию.

Кстати, вы могли бы создать отдельный __timestamp.c файл, содержащий метку времени и контрольную сумму (и я делаю это в моем bismon проект летом 2018 года), и свяжите его с вашим исполняемым файлом.

9

Другие решения


По вопросам рекламы [email protected]