Компилятор C ++ обычно не генерирует код для проверки правильности указателей от вашего имени. Если вам все равно, вам нужно предоставить код самостоятельно. Поскольку доступ к свободной памяти вызывает неопределенное поведение, результат этого не является детерминированным.
В любом случае вы не должны манипулировать необработанными указателями и вместо этого полагаться на один из интеллектуальных указателей для вас. Тогда вы гораздо менее склонны сталкиваться с этой ошибкой, так как вы будете полагаться на указатель, выпадающий из области действия, чтобы можно было уничтожить память.
Однако даже при этом вы все равно можете столкнуться с случаями где вы вынуждаете плохие вещи, например:
std::unique_ptr<Foo> p(new Foo);
p->foo();
p.reset(0);
p->foo();
Вы можете попытаться поймать такие проблемы во время выполнения с помощью оболочки интеллектуального указателя, которая выполняет определенную форму проверки для вас:
template <typename T>
class CheckedSharedPtr {
std::shared_ptr<T> ptr_;
public:
//...
T * operator -> () const {
if (ptr_ == 0) {
//...throw something
}
return ptr_.operator->();
}
};
Но это просто добавляет дополнительные накладные расходы для каждого доступа к указателю. Лучший способ - использовать хороший инструмент для анализа статического кода, который может помочь идентифицировать эти проблемы в вашем коде, а также многие другие.
Существует три основных подхода для этой проблемы.
h()
в Ваших представлениях. Оборотная сторона здесь - то, что, если Вы забываете, Вы получаете pwnd.h()
в Ваших представлениях (главным образом). Существуют другие, которые работают на уровне контроллера. Оборотные стороны здесь - (a) то, если существует ошибка в коде выхода, Вы могли бы получить XSS в своей базе данных; и (b) Существуют угловые случаи, где Вы все еще захотите использовать h()
.Затем существуют некоторые гибридные подходы.
Нет никакой причины, почему Вы не можете использовать xss_terminate и CrossSiteSniper одновременно.
Существует также реализация ERb под названием Erubis, который может быть настроен так, чтобы любой вызов как <%= foo.name %>
оставлен - эквивалент <%= h(foo.name) %>
. К сожалению, Erubis всегда, кажется, отстает от направляющих, и так использование его может замедлить Вас.
Если Вы хотите читать больше, я записал сообщение в блоге (который Xavor, любезно связанный с) об использовании xss_terminate.
Или с этим плагином - нет необходимости в h 8)
http://railspikes.com/2008/1/28/auto-escaping-html-with-rails
H является псевдонимом для html_escape, который является служебным методом для выхода из всех символов HTML-тэга:
html_escape('<script src=http://ha.ckers.org/xss.js></script>')
# => <script src=http://ha.ckers.org/xss.js></script>
При необходимости в большем количестве управления пойдите с санировать методом, который может использоваться в качестве белого списка тегов и атрибутов для разрешения:
sanitize(@article.body, :tags => %w(table tr td), :attributes => %w(id class style))
Я позволил бы пользователю вводить что-либо, хранить его как есть в базе данных и Escape при отображении его. Тем путем Вы не теряете вводимой информации. Можно всегда настроить логику выхода позже...
Используйте h метод в своем шаблоне представления. Скажите, что у Вас есть объект сообщения со свойством комментария:
<div class="comment">
<%= h post.comment %>
</div>
Я только что выпустил плагин под названием ActsAsSanitiled , использующий гем Sanitize , который может гарантировать правильную формулировку, а также легко настраивается для HTML разрешен, и все это без изменения пользовательского ввода и без необходимости запоминать что-либо на уровне шаблона.