[Закрываются] любимые (умные) лучшие практики безопасного программирования

Если вы просто хотите удалить ненужные файлы, сделайте следующее:

git clean -df

добавьте x к этому, если вы хотите также включать в себя специально проигнорированные файлы. Я использую git clean -dfx a lot в течение дня.

Вы можете создать пользовательский git, просто написав скрипт под названием git-whatever и имея его в своем пути.

148
задан 3 revs, 2 users 98% 30 January 2009 в 03:04
поделиться

65 ответов

В C++ мне когда-то понравилось переопределять новый так, чтобы он обеспечил некоторую дополнительную память для ловли ошибок на единицу при счете.

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

, Поскольку WikiKnowledge Записал :

Избегают Безопасного программирования, Сбой Быстро Вместо этого.

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

103
ответ дан Joe Soul-bringer 4 November 2019 в 18:20
поделиться

SQL

, Когда я должен удалить данные, я пишу

select *    
--delete    
From mytable    
Where ...

, Когда я выполню его, я буду знать, забыл ли я или испортил где пункт. У меня есть безопасность. Если все прекрасно, я выделяю все после '-' маркеры комментария и выполняю его.

Редактирование: если я удалю много данных, то я буду использовать количество (*) вместо просто *

75
ответ дан 4 revs, 3 users 82% 4 November 2019 в 18:20
поделиться

Выделите разумный блок памяти, когда приложение запускается - я думаю, что Steve McConnell назвал это парашют памяти в Завершенном Коде.

Это может использоваться в случае, если что-то серьезное идет не так, как надо, и Вы обязаны завершаться.

Выделение этой памяти заранее предоставляет Вам систему поддержки, поскольку можно освободить его и затем использовать доступную память, чтобы сделать следующее:

  • Сохраняют все персистентные данные
  • Близкий все соответствующие файлы
  • сообщения Ошибки при записи к файлу журнала
  • Существующий значимая ошибка пользователю
48
ответ дан LeopardSkinPillBoxHat 4 November 2019 в 18:20
поделиться

В каждом операторе переключения, который не имеет случая по умолчанию, я добавляю случай, который прерывает программу с сообщением об ошибке.

#define INVALID_SWITCH_VALUE 0

switch (x) {
case 1:
  // ...
  break;
case 2:
  // ...
  break;
case 3:
  // ...
  break;
default:
  assert(INVALID_SWITCH_VALUE);
}
42
ответ дан 2 revs, 2 users 95% 4 November 2019 в 18:20
поделиться

Когда Вы обрабатываете различные состояния перечисления (C#):

enum AccountType
{
    Savings,
    Checking,
    MoneyMarket
}

Затем в некоторой стандартной программе...

switch (accountType)
{
    case AccountType.Checking:
        // do something

    case AccountType.Savings:
        // do something else

    case AccountType.MoneyMarket:
        // do some other thing

    default:
-->     Debug.Fail("Invalid account type.");
}

В какой-то момент я добавлю другой тип учетной записи к этому перечислению. И когда я делаю, я забуду фиксировать этот оператор переключения. Так Debug.Fail катастрофические отказы ужасно (в Режиме отладки) для привлечения моего внимания к этому факту. Когда я добавляю эти case AccountType.MyNewAccountType:, ужасные остановки катастрофического отказа..., пока я не добавляю еще один тип учетной записи и забываю обновлять случаи здесь.

(Да, полиморфизм, вероятно, лучше здесь, но это - просто пример первое, что пришло на ум.)

41
ответ дан 2 revs, 2 users 92% 4 November 2019 в 18:20
поделиться

Безопасность SQL

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

BEGIN TRANSACTION
-- LOTS OF SCARY SQL HERE LIKE
-- DELETE FROM ORDER INNER JOIN SUBSCRIBER ON ORDER.SUBSCRIBER_ID = SUBSCRIBER.ID
ROLLBACK TRANSACTION

Это препятствует, Вы выполнить плохое удаляете/обновляете постоянно. И, можно выполнить все это и проверить разумные количества записей или добавить SELECT операторы между SQL и ROLLBACK TRANSACTION, чтобы удостовериться, что все выглядит правильным.

, Когда Вы абсолютно уверены, что это делает то, что Вы ожидали, изменение ROLLBACK к COMMIT и выполняли для реального.

28
ответ дан 2 revs, 2 users 88% 4 November 2019 в 18:20
поделиться

При распечатывании сообщений об ошибках со строкой (особенно та, которая зависит от ввода данных пользователем), я всегда использую одинарные кавычки ''. Например:

FILE *fp = fopen(filename, "r");
if(fp == NULL) {
    fprintf(stderr, "ERROR: Could not open file %s\n", filename);
    return false;
}

Это отсутствие кавычек приблизительно %s действительно плохи, потому что говорят, что имя файла является пустой строкой или просто пробелом или чем-то. Распечатанное сообщение, конечно, было бы:

ERROR: Could not open file

Так, всегда лучше, чтобы сделать:

fprintf(stderr, "ERROR: Could not open file '%s'\n", filename);

Затем, по крайней мере, пользователь видит это:

ERROR: Could not open file ''

я нахожу, что это имеет огромное значение с точки зрения качества отчетов об ошибках, отправленных конечными пользователями. Если существует забавно выглядящее сообщение об ошибке как это вместо чего-то универсальное звучание, то они намного более вероятны скопировать/вставить им вместо того, чтобы просто писать, что "оно не открыло бы мои файлы".

35
ответ дан 2 revs, 2 users 69% 4 November 2019 в 18:20
поделиться

Для всех языков:

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

25
ответ дан 2 revs 4 November 2019 в 18:20
поделиться

Когда в сомнении, бомбите приложение!

Проверка каждый параметр в начале каждый метод (не имеет ли explictly кодирование его самостоятельно или использование основанного на контракте программирования значения здесь) и бомбят за корректным исключением и/или значимым сообщением об ошибке, если любое предварительное условие к коду не встречено.

Все мы знаем об этих неявных предварительных условиях , когда мы пишем код , но если они явно не проверяются на, мы создаем лабиринты для нас, когда что-то идет не так, как надо позже, и стопки десятков вызовов метода разделяют происшествие признака и фактического местоположения, где предварительное условие не встречено (=where, проблема/ошибка на самом деле).

19
ответ дан 2 revs 4 November 2019 в 18:20
поделиться

В Java, особенно с наборами, используют API, поэтому если Ваш метод возвращает список типов (например), попробуйте следующее:

public List<T> getList() {
    return Collections.unmodifiableList(list);
}

не позволяют ничему выходить из Вашего класса, что Вы не должны!

18
ответ дан 4 revs, 3 users 71% 4 November 2019 в 18:20
поделиться

в Perl все делают

use warnings;

, мне нравится

use warnings FATAL => 'all';

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

use warnings FATAL => 'all';
...
my $string = getStringVal(); # something bad happens;  returns 'undef'
print $string . "\n";        # code dies here
17
ответ дан 3 revs, 2 users 82% 4 November 2019 в 18:20
поделиться

C#:

string myString = null;

if (myString.Equals("someValue")) // NullReferenceException...
{

}

if ("someValue".Equals(myString)) // Just false...
{

}
16
ответ дан 2 revs, 2 users 93% 4 November 2019 в 18:20
поделиться

В проверке c# строки. IsNullOrEmpty прежде, чем сделать любые операции на строке как длина, indexOf, середина и т.д.

public void SomeMethod(string myString)
{
   if(!string.IsNullOrEmpty(myString)) // same as myString != null && myString != string.Empty
   {                                   // Also implies that myString.Length == 0
     //Do something with string
   }
}

[Редактирование]
Теперь я могу также сделать следующее в.NET 4.0, который дополнительно проверяет, является ли значение просто пробелом

string.IsNullOrWhiteSpace(myString)
15
ответ дан 3 revs 4 November 2019 в 18:20
поделиться

В Java и C#, дайте каждый , распараллеливают понятное имя. Это включает потоки пула потоков. Это делает дампы стека намного более значимыми. Прилагает немного больше усилий дать понятное имя даже потокам пула потоков, но если один пул потоков имеет проблему в длительном приложении, я могу заставить дамп стека происходить (Вы действительно знаете приблизительно SendSignal.exe , правильно?), захватите журналы, и не имея необходимость прерывать рабочую систему, которую я могу сказать, который потоки... без разницы. Заведенный в тупик, утечка, рост, независимо от того, что проблема.

14
ответ дан 2 revs, 2 users 67% 4 November 2019 в 18:20
поделиться

С VB.NET имейте Явную Опцию и Опцию, Строгую включенный по умолчанию для всей Visual Studio.

12
ответ дан ChrisA 4 November 2019 в 18:20
поделиться

В Java, когда что-то происходит и я не знаю, почему, я буду иногда использовать Log4J как это:

if (some bad condition) {
    log.error("a bad thing happened", new Exception("Let's see how we got here"));
}

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

9
ответ дан Eddie 4 November 2019 в 18:20
поделиться

С Java может быть удобно использовать утверждать ключевое слово даже при выполнении производственного кода с выключенными утверждениями:

private Object someHelperFunction(Object param)
{
    assert param != null : "Param must be set by the client";

    return blahBlah(param);
}

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

10
ответ дан 2 revs, 2 users 90% 4 November 2019 в 18:20
поделиться

Я не нашел readonly ключевое слово, пока я не нашел ReSharper, но я теперь использую его инстинктивно, специально для классов обслуживания.

readonly var prodSVC = new ProductService();
9
ответ дан JMS 4 November 2019 в 18:20
поделиться

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

кроме того, 'strace-p [pid]' на Linux покажет, Вы хотите системные вызовы, которые делает процесс (или поток Linux). Это может выглядеть странным сначала, но после того как Вы привыкаете к тому, какие системные вызовы обычно делаются тем, что называет libc, Вы найдете это неоценимым для в полевом диагнозе.

4
ответ дан dicroce 4 November 2019 в 18:20
поделиться

C++

, Когда я ввожу новый, я должен сразу ввести, удаляют. Специально для массивов.

Проверка C#

на пустой указатель прежде, чем получить доступ к свойствам, особенно при использовании шаблона Посредника. Объекты передаются (и затем должен быть брошен с помощью как, как был уже отмечен), и затем проверьте по пустому указателю. Даже если Вы думаете, что это не будет пустым, проверить так или иначе. Я был удивлен.

4
ответ дан mmr 4 November 2019 в 18:20
поделиться

Я забыл писать echo в PHP слишком много раз:

<td><?php $foo->bar->baz(); ?></td>
<!-- should have been -->
<td><?php echo $foo->bar->baz(); ?></td>

Это взяло бы меня навсегда, чтобы попытаться выяснить, почему-> baz () ничего не возвращал, когда на самом деле я просто не повторял его!:-S Таким образом, я сделал EchoMe класс, который мог быть перенесен вокруг любого значения, которое должно быть отражено:

<?php
class EchoMe {
  private $str;
  private $printed = false;
  function __construct($value) {
    $this->str = strval($value);
  }
  function __toString() {
    $this->printed = true;
    return $this->str;
  }
  function __destruct() {
    if($this->printed !== true)
      throw new Exception("String '$this->str' was never printed");
  }
}

И затем для среды разработки, я использовал EchoMe для обертывания вещей, которые должны быть распечатаны:

function baz() {
  $value = [...calculations...]
  if(DEBUG)
    return EchoMe($value);
  return $value;
}

Используя ту технику, первый пример, отсутствующий эти echo, теперь выдал бы исключение...

5
ответ дан 2 revs 4 November 2019 в 18:20
поделиться

Будьте подготовлены к любой вход и любой вход, который Вы получаете, который неожидан, дамп к журналам. (В причине. При чтении паролей от пользователя не выводите это к журналам! И не регистрируйте тысячи этих видов сообщений к журналам в секунду. Причина о содержании и вероятности и частоте перед входом его.)

я только говорю о проверке ввода данных пользователем. Например, если Вы читаете Запросы HTTP, что Вы ожидаете содержать XML, готовиться к другим форматам данных. Я был удивлен видеть ответы HTML, где я ожидал только XML - пока я не смотрел и видел, что мой запрос проходил прозрачный прокси, о котором я не знал и что клиент требовал незнания - и прокси привел к таймауту попытки завершить запрос. Таким образом прокси возвратил ошибочную страницу HTML моему клиенту, путая heck из клиента, который ожидал только данные XML.

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

6
ответ дан Eddie 4 November 2019 в 18:20
поделиться

Я пытаюсь использовать Дизайн подхода Контракта. Это может быть эмулированное время выполнения любым языком. Каждые поддержки языка "утверждают", но это легко и covenient для записи лучшей реализации, которые позволяют Вам управлять ошибкой более полезным способом.

В Лучшие 25 Самых Опасных Программных ошибок "Неподходящий Контроль ввода" является самой опасной ошибкой в разделе "Insecure Interaction Between Components".

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

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

я оцениваю Библиотека Контракта Кода .

6
ответ дан Zen 4 November 2019 в 18:20
поделиться

В C# используйте as ключевое слово для кастинга.

string a = (string)obj

выдаст исключение, если obj не будет строкой

string a = obj as string

, то уедет как пустой указатель, если obj не будет строкой

, все еще необходимо принять пустой указатель во внимание, но это является обычно более прямым затем ищущее исключения броска. Иногда Вы хотите "бросок или аварийное завершение" поведение типа, в этом случае (string)obj, синтаксис предпочтен.

В моем собственном коде, я нахожу, что использую as синтаксис приблизительно 75% времени, и (cast) синтаксис приблизительно 25%.

7
ответ дан 3 revs, 2 users 95% 4 November 2019 в 18:20
поделиться

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

"Разрешение, отклоненное", говорит Вам, что была проблема разрешения, но Вы понятия не имеете, почему или где проблема произошла. "Не может транзакция записи регистрировать/my/file: файловая система только для чтения", по крайней мере, сообщает основание, о котором было принято решение, даже если неправильно - особенно, если это неправильно: неправильное имя файла? открытый неправильно? другая неожиданная ошибка? - и сообщает, где Вы были, когда у Вас была проблема.

8
ответ дан Joe McMahon 4 November 2019 в 18:20
поделиться

Если Вы используете Visual C++, используете ключевое слово переопределения каждый раз, когда Вы переопределяете метод базового класса. Таким образом, если кто-либо когда-нибудь, оказывается, изменяет подпись базового класса, она бросит ошибку компилятора, а не неправильный тихо называемый метод. Это сохранило бы меня несколько раз, если бы это существовало ранее.

Пример:

class Foo
{
   virtual void DoSomething();
}

class Bar: public Foo
{
   void DoSomething() override { /* do something */ }
}
9
ответ дан 2 revs, 2 users 78% 4 November 2019 в 18:20
поделиться

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

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

8
ответ дан Eddie 4 November 2019 в 18:20
поделиться

C++

#define SAFE_DELETE(pPtr)   { delete pPtr; pPtr = NULL; }
#define SAFE_DELETE_ARRAY(pPtr) { delete [] pPtr; pPtr = NULL }

затем замена весь Ваш' удаляет pPtr', и' удаляют [] pPtr' вызовы с SAFE_DELETE (pPtr) и SAFE_DELETE_ARRAY (pPtr)

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

10
ответ дан 2 revs, 2 users 93% 4 November 2019 в 18:20
поделиться

C#

  • Проверяет ненулевые значения для параметров ссылочного типа в открытом методе.
  • я использую sealed много, чтобы классы постарались не представлять зависимости, где я не хотел их. Разрешение наследования должно быть сделано явно и не случайно.
8
ответ дан 2 revs 4 November 2019 в 18:20
поделиться

Java

API Java не имеет никакого понятия неизменных объектов, которое плохо! Финал может помочь Вам в этом случае. Отметьте каждый класс, который неизменен с финалом, и подготовьте класс соответственно .

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

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

Никогда клон использования, используйте конструктор копии .

Узнают, что контракт между равняется и хэш-код. Это нарушается так часто. Проблема - это, не влияет на Ваш код в 99% случаев. Люди перезаписывают, равняется, но не заботьтесь о хэш-коде. Существуют экземпляры, в которых Ваш код может повредиться или ведет себя странный, например, используйте изменяемые объекты в качестве ключей в карте.

6
ответ дан 2 revs 4 November 2019 в 18:20
поделиться
Другие вопросы по тегам:

Похожие вопросы: