Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 10 additions & 1 deletion score/flatbuffers/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
# *******************************************************************************

load("@rules_cc//cc:defs.bzl", "cc_library", "cc_test")
load("//score/flatbuffers/bazel:codegen.bzl", "generate_cpp")

cc_library(
name = "flatbufferscpp",
Expand Down Expand Up @@ -140,11 +141,19 @@ cc_test(
],
)

generate_cpp(
name = "array_cast_fixture_generated",
output = "details/array_cast_fixture_generated.h",
schema = "details/array_cast_fixture.fbs",
)

cc_test(
name = "flatbuffers_cpp_library_test",
testonly = True,
srcs = [
"details/flatfbuffer_allocator_test.cpp",
"details/flatbuffers_allocator_test.cpp",
"details/flatbuffers_array_test.cpp",
":array_cast_fixture_generated",
],
deps = [
":flatbufferscpp",
Expand Down
31 changes: 31 additions & 0 deletions score/flatbuffers/details/array_cast_fixture.fbs
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
// ******************************************************************************
// Copyright (c) 2026 Contributors to the Eclipse Foundation
//
// See the NOTICE file(s) distributed with this work for additional
// information regarding copyright ownership.
//
// This program and the accompanying materials are made available under the
// terms of the Apache License Version 2.0 which is available at
// https://www.apache.org/licenses/LICENSE-2.0
//
// SPDX-License-Identifier: Apache-2.0
// ******************************************************************************

// Fixture schema for the end-to-end test demanded by flatbuffers_array_cast_safety.md
namespace score.flatbuffers.test.arrays_fixture;

enum TestEnum : byte { A, B, C }

struct NestedStruct {
coordinates:[int:2];
status:TestEnum;
channel_modes:[TestEnum:2];
timestamps:[int64:2];
}

// root table
table ArraysHolder {
nested:NestedStruct;
}

root_type ArraysHolder;
51 changes: 51 additions & 0 deletions score/flatbuffers/details/flatbuffers_array_cast_safety.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
# Justification why the reinterpret_cast is acceptable

## Claim

`flatbuffers::CastToArray` / `CastToArrayOfEnum` (in `flatbuffers/array.h`)
`reinterpret_cast` a raw `T[length]` into a `flatbuffers::Array<T, length>`. This
violates MISRA C++:2023 Rule 8.2.5 (use of `reinterpret_cast` to an unrelated class type).

This document is the evidence for that claim.

## How the evidence is produced

The schema [`array_cast_fixture.fbs`](array_cast_fixture.fbs) exercises every
fixed-array case — a scalar array, an enum scalar, an enum array and a 64-bit
scalar array. `flatc` compiles it into a `NestedStruct` whose raw C arrays are
`private` and whose constructor and accessors route through `CastToArray` /
`CastToArrayOfEnum`. That generated header is the safe, typed API the user sees.

The end-to-end evidence is [`flatbuffers_array_test.cpp`](flatbuffers_array_test.cpp)
(`ArrayCastSafetyGeneratedTest`), which builds a serialized buffer through
the generated API and reads every field back through the reinterpret-cast view,
verifying each measure below.

## Why this substantiates "measures for correct usage"

The MISRA-flagged `reinterpret_cast` is never in the user's hands. The generated
header enforces:

1. **Encapsulation** — the raw `int32_t a_[2]` storage is `private`; the only
surface is the accessors. Users never call `CastToArray` themselves.
2. **Const-correctness** — read accessors return `const Array<T, N>*`, so the
aliased buffer cannot be mutated through them.
3. **Type safety for enums** — enum arrays route through `CastToArrayOfEnum<E>`,
whose `static_assert(sizeof(E) == sizeof(T), "invalid enum type E")`
(`array.h`) makes a mismatched storage type a compile error.
4. **Size safety for writes** — mutation is only via `CopyFromSpan(span<const T, N>)`.
The span's extent `N` is a compile-time template parameter matching the field
length, so a wrong-length write does not compile.
5. **No uninitialized reads** — padding fields are explicitly zero-initialized in
every constructor.

## Conclusion

The `reinterpret_cast` in `CastToArray` / `CastToArrayOfEnum` is an internal
implementation detail of `array.h`. The `flatc`-generated header is the safe,
typed, const-correct API the user sees.

Correctness of the reinterpret-cast view against a generated buffer is
checked end-to-end by `ArrayCastSafetyGeneratedTest` in
[`flatbuffers_array_test.cpp`](flatbuffers_array_test.cpp). Users of other
generated schemas must provide the equivalent test against their own buffers.
Loading
Loading