Skip to content

3.9: sbytes -> sbytesN cast type-checks but has no codegen, crashing the compiler (ICE) #382

Description

@HenryMBaldwin

Zellic finding 3.9 (Medium, availability). ArrayType::isExplicitlyConvertibleTo accepts sbytesN(sb) (shielded dynamic byte array -> fixed shielded-bytes), but neither codegen backend had a matching branch: CompilerUtils::convertType (legacy) and YulUtilFunctions::conversionFunction (via-IR) only handle a FixedBytes target, so a ShieldedFixedBytes target fell through to a solAssert and aborted with an InternalCompilerError. Any contract using the documented sbytesN(sb) pattern was uncompilable.

Fix (Zellic's two options, split by source location)

  • Memory / calldata source (a plain byte read; the finding's PoC is memory): route through the existing bytesToFixedBytesConversionFunction, mirroring bytes -> bytesN. Guard broadened in both backends and both source kinds (Array and ArraySlice).
  • Storage source: rejected at the type checker with a user-facing error instead of crashing. A correct storage conversion needs a shielded-layout-aware read (cload against the array's data area); the public conversion machinery bakes in the public bytes layout and returns 0 for a shielded storage source, so routing it there would replace the ICE with silent data corruption. Rejecting is Zellic's sanctioned alternative and steers to the working memory form:

    Conversion of a shielded byte array in storage to a fixed shielded-bytes type is not supported; copy it to memory first (e.g. sbytesN(sbytes memory)).

Why not full storage support here

The storage path is a genuine codegen feature (shielded data-area read in both backends, full semantic verification), not routing. This resolves the actual finding (the crash) and delivers the common case correctly; direct-from-storage conversion can be a follow-up.

Tests

  • shielded_sbytes_memory_to_fixed.sol (new semantic): memory + calldata-slice sources, verified against the public bytesN baseline across all four pipeline configs.
  • sbytes_dynamic_to_fixed.sol, sbytes_dynamic_conversions.sol: were syntax-only and asserted the storage cast type-checks (never running codegen where it crashed); updated to cover memory-allowed + storage-rejected.
  • Full syntax suite green; semanticTests/types + conversions regression-swept clean.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions