1 В избранное 0 Ответвления 0

OSCHINA-MIRROR/shike-boringssl

Клонировать/Скачать
STYLE.md 14 КБ
Копировать Редактировать Web IDE Исходные данные Просмотреть построчно История
gitlife-traslator Отправлено 01.12.2024 14:16 972c04e

Руководство по стилю BoringSSL

BoringSSL обычно следует руководству по стилю Google C++ (https://google.github.io/styleguide/cppguide.html). Остальная часть этого документа описывает различия и уточнения на основе базового руководства.

Устаревший код

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

Модули из устаревшего стека ASN.1 и X.509 OpenSSL сохраняются для совместимости и остаются практически неизменными. Чтобы упростить импорт патчей из вышестоящего источника, они соответствуют новому стилю отступов OpenSSL. Для Emacs может быть полезен doc/openssl-c-indent.el из OpenSSL.

Язык

Большая часть проекта написана на языке C, поэтому правила C++, специфичные для Google, не применяются. Поддержка функций C99 зависит от целевых платформ. Как правило, MSVC Chromium является наиболее ограничивающим.

Объявления переменных в середине функции или внутри цикла for разрешены и предпочтительны, где это возможно. Обратите внимание, что общий шаблон очистки goto err требует переноса некоторых объявлений переменных.

Комментарии должны быть // C99-style для соответствия C++.

При объявлении типов указателей * следует размещать рядом с именем переменной, а не с типом. Таким образом:

uint8_t *ptr;

а не

uint8_t* ptr;

Вместо malloc() и free() используйте оболочки OPENSSL_malloc() и OPENSSL_free(), а также свободно используйте стандартную функцию C assert().

Используйте следующие оболочки, найденные в crypto/internal.h, вместо соответствующих функций стандартной библиотеки C. Они ведут себя так же, но избегают путаницы с неопределённым поведением.

  • OPENSSL_memchr
  • OPENSSL_memcmp
  • OPENSSL_memcpy
  • OPENSSL_memmove
  • OPENSSL_memset

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

libssl

libssl изначально был написан на C, но постепенно переписывается на C++11. На момент написания большая часть стиля соответствует нашим соглашениям C, а не Google C++. Кроме того, libssl в Linux в настоящее время может не зависеть от среды выполнения C++. См. утилиты C++ в ssl/internal.h для замены проблемных конструкций C++. Скрипт util/check_imported_libraries.go можно использовать со сборкой разделяемой библиотеки, чтобы проверить, подходит ли новый конструктор.

Если вы не уверены, подберите код окружения. Расхождения между ним и стилем Google C++ будут устранены со временем.

Форматирование

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

if (foo) {
  do_something();
}

а не:

if (foo)
  do_something();

Целые числа

Предпочитайте использовать явно заданные целые числа там, где это уместно, а не общие C. Например, для представления байта используйте uint8_t, а не unsigned char. Аналогично представляйте двухбайтовое поле как uint16_t, а не как unsigned short.

Размеры представлены как size_t.

В структуре, которая сохраняется в течение всего времени жизни SSL-соединения, если границы размера известны и это легко сделать, используйте меньший целочисленный тип, такой как uint8_t. Это «бесплатная» оптимизация занимаемого места соединения для серверов. Не усложняйте код значительно ради этого, и всё ещё проверяйте границы при передаче в структуру и из неё. Это сужение не должно распространяться на локальные переменные и параметры функций.

При выполнении арифметических операций учитывайте условия переполнения.

За исключением платформенных API, не используйте ssize_t. MSVC его не хватает, и предпочитайте внеполосное сигнализирование об ошибках для size_t (см. Возвращаемые значения).

Именование

Следуйте соглашениям об именах Google в файлах C++. В файлах C используйте следующие соглашения об именах для обеспечения согласованности с существующими стилями OpenSSL и C:

Определите структуры с помощью typedef с именем TYPE_NAME. Соответствующая структура должна называться struct type_name_st.

Назовите общедоступные функции как MODULE_function_name, если только функция не является конструктором или деструктором. Модуль

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

Некоторые типы выделяются в библиотеке, в то время как другие инициализируются в структуру, выделяемую вызывающей стороной, часто в стеке. Назовите эти функции TYPE_NAME_new/TYPE_NAME_free и TYPE_NAME_init/TYPE_NAME_cleanup соответственно. Все функции TYPE_NAME_free должны ничего не делать при вводе NULL.

Если переменная имеет длину значения указателя, она имеет суффикс _len. Выходной параметр называется out или имеет префикс out_. Например:

uint8_t *out,
size_t *out_len,
const uint8_t *in,
size_t in_len.

Назовите публичные заголовки, такие как include/openssl/evp.h, с защитными заголовками вроде OPENSSL_HEADER_EVP_H. Назовите внутренние заголовки, например, crypto/ec/internal.h с защитными заголовками, такими как OPENSSL_HEADER_EC_INTERNAL_H.

Именуйте перечисления, например, enum unix_hacker_t. Например:

enum should_free_handshake_buffer_t {
  free_handshake_buffer,
  dont_free_handshake_buffer
};

Возвращаемые значения

Поскольку даже malloc может дать сбой в BoringSSL, подавляющее большинство функций будет иметь случай сбоя. Функции должны возвращать int с единицей при успехе и нулём при ошибке. Не перегружайте возвращаемое значение для обозначения успеха/неудачи и вывода целого числа. Например:

OPENSSL_EXPORT int CBS_get_u16(CBS *cbs, uint16_t *out);

Если функции требуется больше, чем код результата true/false, определите перечисление вместо произвольного присвоения значения целым числам.

Если функция выводит указатель на объект при успешном выполнении и других выходных данных нет, верните указатель напрямую и NULL при ошибке.

Параметры

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

  1. Контекстные параметры.
  2. Выходные параметры.
  3. Входные параметры.

Например:

/* CBB_add_asn устанавливает |*out_contents| в |CBB|, в который можно записать содержимое объекта ASN.1. Аргумент |tag| будет использоваться в качестве тега для объекта. Он возвращает единицу при успехе или ноль при ошибке. */
OPENSSL_EXPORT int CBB_add_asn1(CBB *cbb, CBB *out_contents, unsigned tag);

Документация

Все публичные символы должны иметь комментарий документации в своём заголовочном файле. Стиль основан на стиле Go. Первое предложение начинается с имени символа, возможно, с префикса «A» или «An». Помимо первоначального упоминания символа, ссылки на другие символы или имена параметров должны быть заключены в вертикальные черты.

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

// EVP_DigestVerifyUpdate добавляет |len| байтов из |data| к данным, которые будут проверены |EVP_DigestVerifyFinal|. Возвращает единицу при успехе, иначе ноль.
OPENSSL_EXPORT int EVP_DigestVerifyUpdate(EVP_MD_CTX *ctx, const void *data, size_t len);

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

// RSA_private_encrypt шифрует |flen| байтов от |from| с помощью закрытого ключа в |rsa| и записывает зашифрованные данные в |to|. Буфер |to| должен иметь не менее |RSA_size| байт пространства. Возвращает количество записанных байтов или -1 при ошибке. Аргумент |padding| должен быть одним из значений |RSA_*_PADDING|. Если сомневаетесь, |RSA_PKCS1_PADDING| — наиболее распространённый вариант.
//
// ВНИМАНИЕ: эта функция опасна, поскольку нарушает обычную конвенцию о возвращаемом значении. Вместо этого используйте |RSA_sign_raw|.
OPENSSL_EXPORT int RSA_private_encrypt(int flen, const uint8_t *from, uint8_t *to, RSA *rsa, int padding);

Документируйте частные функции в их заголовке internal.h или, если они статические, там, где они определены.

Логика сборки

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

Опубликовать ( 0 )

Вы можете оставить комментарий после Вход в систему

1
https://api.gitlife.ru/oschina-mirror/shike-boringssl.git
git@api.gitlife.ru:oschina-mirror/shike-boringssl.git
oschina-mirror
shike-boringssl
shike-boringssl
master