Skip to content

proposal: cmd/asm: support for mutation testing #75315

@FiloSottile

Description

@FiloSottile

Test coverage for cryptographic assembly is worthless, because branches are intentionally avoided for constant timedness, and control flow and edge cases are hidden with CMOV and ADC instructions. A few years ago I tried dynamic instrumentation to observe flag states, but it quickly turned unwidely, and it's not portable.

Mutation testing provides effectively a coverage replacement: if we mutate a CMOV first to a MOV, and then to a NOP, and tests fail in both cases, it means we are covering both "branches".

Applying mutations to the assembler input is difficult due to macro expansion, so it'd be best to have assembler support.

I propose adding a -mutlist flag which prints an instruction listing to stderr in format asm: mutlist: FILEPATH:LINE: PC INSTR with virtual PCs (the potential targets) and a mutually exclusive -mut flag which accepts a mutation in the format FILEPATH:PC=INSTR[;INSTR].

$ go test crypto/ed25519 -asmflags=crypto/internal/fips140/edwards25519/field=-mutlist -c
# crypto/internal/fips140/edwards25519/field
asm: mutlist: $GOROOT/src/crypto/internal/fips140/edwards25519/field/fe_amd64.s:8: 00001 TEXT   crypto/internal/fips140/edwards25519/field.feMul(SB), NOSPLIT, $0-24
[...]
asm: mutlist: $GOROOT/src/crypto/internal/fips140/edwards25519/field/fe_amd64.s:23: 00012 ADDQ  AX, DI
asm: mutlist: $GOROOT/src/crypto/internal/fips140/edwards25519/field/fe_amd64.s:24: 00013 ADCQ  DX, SI
asm: mutlist: $GOROOT/src/crypto/internal/fips140/edwards25519/field/fe_amd64.s:27: 00014 MOVQ  16(CX), DX
[...]

$ go test crypto/ed25519 -asmflags=crypto/internal/fips140/edwards25519/field='"-mut=$GOROOT/src/crypto/internal/fips140/edwards25519/field/fe_amd64.s:13=STC;ADCQ DX, SI"'
--- FAIL: TestGenerateKey (0.00s)
panic: runtime error: invalid memory address or nil pointer dereference [recovered, repanicked]
[signal SIGSEGV: segmentation violation code=0x1 addr=0x0 pc=0x5a900de]

The PCs need to be virtual to avoid having to recompute them after inserting/mutating instructions.

There is an implementation in CL 665375, and a mutation test framework that uses it in CL 666395. I wrote more about the use case here.

/cc @golang/compiler

Metadata

Metadata

Assignees

No one assigned

    Labels

    ProposalToolProposalIssues describing a requested change to a Go tool or command-line program.compiler/runtimeIssues related to the Go compiler and/or runtime.

    Type

    No type

    Projects

    Status

    No status

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions