floatnum

package
v0.96.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Nov 7, 2026 License: MIT Imports: 9 Imported by: 0

Documentation

Overview

Package floatnum catches JSON decoded into a target that holds an interface value (any, map[string]any, []any, or a struct field of one) without UseNumber. encoding/json stores every number under an interface as a float64, so an integer past 2^53 comes back with different digits: 9007199254740993 reads as 9007199254740992.

The bug class: the 2026-10-26 bug bash fixed about fifteen of these — typed hooks round-tripping a field through `var decoded any`, MCP tool arguments and results, the generated Go client and CLI, semantic search metadata and its HTTP routes, MCP enum comparison, JSON fields in CRUD. Each was a json.Unmarshal or Decoder.Decode into an interface-holding value. The fix decodes through a json.Decoder that calls UseNumber (internal/jsonexact.Unmarshal does that and converts each json.Number), or passes handler.UseNumber() to handler.UnmarshalStrict.

It fires on json.Unmarshal, (*json.Decoder).Decode, and handler.UnmarshalStrict / handler.DecodeStrict, and stays silent when:

  • the decoder is a local whose UseNumber() is called in the same function, or UnmarshalStrict is passed handler.UseNumber(), directly or through a variable that holds it (a local or package-level option, a []StrictOption literal or append that includes it, spread with `opts...`; ledger I3 of the 2026-10-27 bug bash was the variable form reporting);
  • the target holds no empty interface (typed numbers keep their Go types), or reaches one only through a type with its own UnmarshalJSON (json.RawMessage is one);
  • the file is a _test.go file.

A destination that is an interface parameter (`func decode(b []byte, v any)`) has its type at the caller. Such a function exports a lossyParams fact naming the parameter, a wrapper that hands its own interface parameter on inherits it, and the report lands on the call that passes a pointer to an interface-holding type, in this package or any importer. The A2A JSON-RPC decodeParams and kiln's journal Entry.Decode were that shape, and the pointer-only check missed both.

A decode whose numbers are never read (only a string discriminator is looked at) carries //gofastr:allow(floatnum) <why>. On a passthrough decode the marker also keeps the fact from being exported.

Index

Constants

This section is empty.

Variables

View Source
var Analyzer = &analysis.Analyzer{
	Name:      "floatnum",
	Doc:       "forbids decoding JSON into an interface-holding value without UseNumber; integers past 2^53 lose digits as float64",
	Run:       run,
	FactTypes: []analysis.Fact{(*lossyParams)(nil)},
}

Functions

This section is empty.

Types

This section is empty.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL