Я СКАЗАЛ, что вы, Gotos опасны!


Недавний недостаток безопасности в iOS связан с ошибкой, связанной с ложным оператором goto, но если вы присмотритесь, можно извлечь более важный урок из инцидента, а не просто «goto считается вредным».

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

Адам Лэнгли, эксперт по веб-шифрованию в Google, покопался и обнаружил, что все дело в одном дополнительном переходе.

Все мы знаем, что goto вреден, но неужели это еще не все?

Нажмите на этот мультфильм Joy of Tech, чтобы увидеть оставшиеся девять кадров.

Не поймите меня неправильно; goto ЯВЛЯЕТСЯ вредным, но потому что это один из ярких примеров неструктурированного кодирования — противоположность структурированного кодирования.

В хорошо структурированной программе используются блоки операторов, которые подходят друг к другу, как Lego, и не могут быть использованы неправильно. Хорошо, на самом деле это «меньше шансов быть использовано неправильно».

Взгляните на код, вызвавший проблему:

if ((err = SSLHashSHA1.update (& hashCtx, & serverRandom))! = 0) перейти к ошибке;

если ((err = SSLHashSHA1.update (& hashCtx, & signedParams))! = 0)

перейти к неудаче;

перейти к неудаче;

если ((err = SSLHashSHA1.final (& hashCtx, & hashOut))! = 0)

перейти к неудаче;

ошибка: справиться с ошибкой

Вы видите эту глупую ошибку?

Второй оператор if связан только с первым отказом goto, несмотря на отступ (если бы это был Python!).

Правильный отступ делает ошибку совершенно ясной:

if ((err = SSLHashSHA1.update (& hashCtx, & serverRandom))! = 0) перейти к ошибке; if ((err = SSLHashSHA1.update (& hashCtx, & signedParams))! = 0) перейти к ошибке; перейти к неудаче; if ((err = SSLHashSHA1.final (& hashCtx, & hashOut))! = 0) перейти к ошибке; …

Проблема усугубляется тем фактом, что err содержит успешное значение, даже если оно было передано обработчику ошибок для обработки, а это означает, что проверка подписи никогда не завершается ошибкой.

Как это случилось!

Я предполагаю, что программист скопировал и вставил в код «goto fail» и просто дважды нажал клавиши.

Что могло бы помешать этому случиться?

На этом этапе вы могли бы захотеть вмешаться с «запретить goto» — я знаю, что хотел бы, но на самом деле проблема не в этом.

Простой редактор автоформатирования привлек бы внимание программиста к проблеме, даже если бы не защищал от нее.

Наличие мертвого кода флага компилятора также могло бы выявить проблему — по умолчанию ни GCC, ни Clang в мертвом коде флага Xcode.

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

Возможно, наиболее широкое решение — просто не использовать каскадные If с goto, используемым в качестве выхода. Большая проблема в том, как реализовать это на C / C ++ в виде структурированного оператора. Вы не можете использовать переключатель, потому что C / C ++ допускает только постоянные выражения в каждом тесте и, следовательно, вы не можете выполнять вызовы функций. Не говоря уже о том, что у переключателя C / C ++ есть свои проблемы с необходимостью включать разрыв.

Лучшее, что вы можете сделать, это использовать вложенные if:

if ((err = SSLHashSHA1.update (& hashCtx, & serverRandom))! = 0) {вызов функции ошибки

}

else if ((err = SSLHashSHA1.update (& hashCtx, & signedParams))! = 0 {функция ошибки вызова

} else if ((err = SSLHashSHA1.final (& hashCtx, & hashOut))! = 0) {

вызов функции ошибки

} else {процесс успешно}

Это настолько ясно, насколько это возможно?

Думаю, нет.

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

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

Так есть ли лучший способ в C / C ++?

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

Источник: joyof tech.com

Кто бы мог подумать, что один лишний goto может вызвать столько проблем!


Добавить комментарий