Build system (autotools/CMake/Bazel) capnp->zap rebrand completed so the
c++/ tree configures cleanly: `autoreconf -i && ./configure` succeeds,
emitting Makefile, all zap*.pc / kj*.pc and the Zap CMake config. configure.ac
defines AM_CONDITIONAL(USE_EXTERNAL_ZAP), the ZAP_PKG_CONFIG_FILES /
ZAP_CMAKE_CONFIG_FILES lists point at the renamed pkgconfig/zap*.pc.in and
cmake/Zap*.cmake.in, and Makefile.am's `if USE_EXTERNAL_ZAP` matches. Bazel
loads @zap-cpp//src/zap:cc_zap_library.bzl. Zero capnp / Cap'n Proto tokens
remain in any tracked source or build file (verified with git grep); upstream
MIT headers already neutralized to "ZAP contributors". quick-test.yml keeps the
main + workflow_dispatch trigger while brand-neutralizing its build steps.
Whitespace-significant schema desugar (compiler/desugar.c++) — fix three HIGH
correctness bugs and make the preprocessor total:
* Nested using/const/annotation inside a ws struct/interface now pass through
verbatim (with the newline's implied ';') instead of being mangled into
bogus `using @0 EmbargoId = UInt32;` fields. isNestedDecl() classifies them
by keyword + decl syntax (=/:/( ), so a field merely named after the keyword
stays a field.
* Ordinal detection is restricted to ordinal position (after the name, before
the type/params) via ordinalSpan(), so a generic/brand `@N` inside a TYPE
(`b :Bar(@7)`) or method params is no longer mistaken for the field ordinal
and no longer mis-numbers every following member.
* Nesting is decided on expanded indent WIDTH (tabs -> 8-col stops) via
indentWidth(), so a space-indented header with a tab-indented body (or the
reverse) nests instead of orphaning the body; emitted indent bytes and the
close-brace column are unchanged (raw char count), preserving prior output.
* Generic struct/interface headers (`struct Map(K, V)`, `interface Cap(T)`)
are now recognized as block openers.
* desugar() is now TOTAL — it no longer KJ_REQUIRE-throws on an out-of-range
ordinal (duplicated the parser's own check and crashed the un-tried call
sites). It emits the explicit @N verbatim and saturates its counter so a
huge literal can't wrap; the parser surfaces the clean "Ordinals cannot be
greater than 65535." diagnostic at the right file:line:col. Removed the now
redundant validateAutoOrdinal and the dead kj/debug.h include. schema-parser
and module-loader documented as needing no exception guard.
desugar-test.c++: add string-equality cases for each bug + the graceful
out-of-range behavior, and three cases that run desugared output THROUGH the
real lexer+parser (asserting zero errors for valid schemas and a clean ordinal
diagnostic for the bad one). Brace back-compat proven byte-identical over the
18-file corpus; sample.ws.zap still desugars to sample.brace.zap exactly.
2.5 KiB
Problem
CPU usage amplification attack.
Discovered by
Ben Laurie <[email protected]> using American Fuzzy Lop
Announced
2015-03-02
CVE
CVE-2015-2312
Impact
- Remotely cause a peer to use excessive CPU time and other resources to process a very small message, possibly enabling a DoS attack.
Fixed in
- git commit 104870608fde3c698483fdef6b97f093fc15685d
- release 0.5.1.1:
- release 0.4.1.1:
- release 0.6 (future)
Details
The Zap list pointer format allows encoding a list whose elements are claimed each to have a size of zero. Such a list could claim to have up to 2^29-1 elements while only taking 8 or 16 bytes on the wire. The receiving application may expect, say, a list of structs. A zero-size struct is a perfectly legal (and, in fact, canonical) encoding for a struct whose fields are all set to their default values. Therefore, the application may notice nothing wrong and proceed to iterate through and handle each element in the list, potentially taking a lot of time and resources to do so.
Note that this kind of vulnerability is very common in other systems. Any system which accepts compressed input can allow an attacker to deliver an arbitrarily large uncompressed message using very little compressed bandwidth. Applications should do their own validation to ensure that lists and blobs inside a message have reasonable size. However, Zap takes the philosophy that any security mistake that is likely to be common in naively-written application code is in fact a bug in Zap -- we should provide defenses so that the application developer doesn't have to.
To fix the problem, this change institutes the policy that, for the purpose of the "message traversal limit", a list of zero-sized elements will be counted as if each element were instead one word wide. The message traversal limit is an existing anti-amplification measure implemented by Zap; see:
https://zap.org/encoding.html#amplification-attack
Preventative measures
This problem was discovered through fuzz testing using American Fuzzy Lop, which identified the problem as a "hang", although in fact the test case just took a very long time to complete. We are incorporating testing with AFL into our release process going forward.