diff --git a/include/openssl/stack.h b/include/openssl/stack.h index 8f15ea2b..0e59d6a5 100644 --- a/include/openssl/stack.h +++ b/include/openssl/stack.h @@ -222,21 +222,22 @@ struct StackTraits {}; } } -#define BORINGSSL_DEFINE_STACK_TRAITS(name, is_const) \ - extern "C++" { \ - namespace bssl { \ - namespace internal { \ - template <> \ - struct StackTraits { \ - using Type = name; \ - static constexpr bool kIsConst = is_const; \ - }; \ - } \ - } \ +#define BORINGSSL_DEFINE_STACK_TRAITS(name, type, is_const) \ + extern "C++" { \ + namespace bssl { \ + namespace internal { \ + template <> \ + struct StackTraits { \ + static constexpr bool kIsStack = true; \ + using Type = type; \ + static constexpr bool kIsConst = is_const; \ + }; \ + } \ + } \ } #else -#define BORINGSSL_DEFINE_STACK_TRAITS(name, is_const) +#define BORINGSSL_DEFINE_STACK_TRAITS(name, type, is_const) #endif /* Stack functions must be tagged unused to support file-local stack types. @@ -350,15 +351,15 @@ struct StackTraits {}; /* DEFINE_STACK_OF defines |STACK_OF(type)| to be a stack whose elements are * |type| *. */ -#define DEFINE_STACK_OF(type) \ +#define DEFINE_STACK_OF(type) \ BORINGSSL_DEFINE_STACK_OF_IMPL(type, type *, const type *) \ - BORINGSSL_DEFINE_STACK_TRAITS(type, false) + BORINGSSL_DEFINE_STACK_TRAITS(type, type, false) /* DEFINE_CONST_STACK_OF defines |STACK_OF(type)| to be a stack whose elements * are const |type| *. */ -#define DEFINE_CONST_STACK_OF(type) \ +#define DEFINE_CONST_STACK_OF(type) \ BORINGSSL_DEFINE_STACK_OF_IMPL(type, const type *, const type *) \ - BORINGSSL_DEFINE_STACK_TRAITS(type, true) + BORINGSSL_DEFINE_STACK_TRAITS(type, const type, true) /* DEFINE_SPECIAL_STACK_OF defines |STACK_OF(type)| to be a stack whose elements * are |type|, where |type| must be a typedef for a pointer. */ @@ -407,10 +408,62 @@ struct DeleterImpl< } }; +template +class StackIteratorImpl { + public: + using Type = typename StackTraits::Type; + // Iterators must be default-constructable. + StackIteratorImpl() : sk_(nullptr), idx_(0) {} + StackIteratorImpl(const Stack *sk, size_t idx) : sk_(sk), idx_(idx) {} + + bool operator==(StackIteratorImpl other) const { + return sk_ == other.sk_ && idx_ == other.idx_; + } + bool operator!=(StackIteratorImpl other) const { + return !(*this == other); + } + + Type *operator*() const { + return reinterpret_cast( + sk_value(reinterpret_cast(sk_), idx_)); + } + + StackIteratorImpl &operator++(/* prefix */) { + idx_++; + return *this; + } + + StackIteratorImpl operator++(int /* postfix */) { + StackIteratorImpl copy(*this); + ++(*this); + return copy; + } + + private: + const Stack *sk_; + size_t idx_; +}; + +template +using StackIterator = typename std::enable_if::kIsStack, + StackIteratorImpl>::type; + } // namespace internal } // namespace bssl +// Define begin() and end() for stack types so C++ range for loops work. +template +static inline bssl::internal::StackIterator begin(const Stack *sk) { + return bssl::internal::StackIterator(sk, 0); +} + +template +static inline bssl::internal::StackIterator end(const Stack *sk) { + return bssl::internal::StackIterator( + sk, sk_num(reinterpret_cast(sk))); +} + } // extern C++ #endif diff --git a/ssl/ssl_cert.cc b/ssl/ssl_cert.cc index 0fcf48d4..4337ec03 100644 --- a/ssl/ssl_cert.cc +++ b/ssl/ssl_cert.cc @@ -721,9 +721,7 @@ int ssl_add_client_CA_list(SSL *ssl, CBB *cbb) { return CBB_flush(cbb); } - for (size_t i = 0; i < sk_CRYPTO_BUFFER_num(names); i++) { - const CRYPTO_BUFFER *name = sk_CRYPTO_BUFFER_value(names, i); - + for (const CRYPTO_BUFFER *name : names) { if (!CBB_add_u16_length_prefixed(&child, &name_cbb) || !CBB_add_bytes(&name_cbb, CRYPTO_BUFFER_data(name), CRYPTO_BUFFER_len(name))) {