Report a prep-time arg that its check should have caught
calcPrep discarded parseCalc's error, so a divergence from checkCalc would have produced a nil AST and then a nil dereference per render, with no message. atoi did the same quietly, returning zero for a length, range or decimal count. Both now panic naming the argument, so the invariant they rest on fails where it breaks. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
+10
-2
@@ -93,8 +93,16 @@ func generate(f func(rng) string) func([]string) callFn {
|
|||||||
|
|
||||||
const hexDigits = "0123456789abcdef"
|
const hexDigits = "0123456789abcdef"
|
||||||
|
|
||||||
// atoi parses an arg already validated by a builtin's check, so it cannot fail.
|
// atoi parses an arg a builtin's check already validated. It panics rather than
|
||||||
func atoi(s string) int { n, _ := strconv.Atoi(s); return n }
|
// returning zero, so a check that stops covering its own args is a stack trace and
|
||||||
|
// not a silently wrong length, range or decimal count.
|
||||||
|
func atoi(s string) int {
|
||||||
|
n, err := strconv.Atoi(s)
|
||||||
|
if err != nil {
|
||||||
|
panic(fmt.Sprintf("fakes: builtin arg %q reached prep unvalidated: %v", s, err))
|
||||||
|
}
|
||||||
|
return n
|
||||||
|
}
|
||||||
|
|
||||||
func randBytes(r rng, n int) []byte {
|
func randBytes(r rng, n int) []byte {
|
||||||
b := make([]byte, n)
|
b := make([]byte, n)
|
||||||
|
|||||||
@@ -96,7 +96,10 @@ func checkCalc(fields map[string]node, args []string) error {
|
|||||||
// operand name at the position expand will read it into. checkCalc proved both args
|
// operand name at the position expand will read it into. checkCalc proved both args
|
||||||
// valid, so no step here can fail; dp -1 prints the minimal form.
|
// valid, so no step here can fail; dp -1 prints the minimal form.
|
||||||
func calcPrep(args []string) callFn {
|
func calcPrep(args []string) callFn {
|
||||||
expr, _ := parseCalc(args[0])
|
expr, err := parseCalc(args[0])
|
||||||
|
if err != nil { // a nil AST would be a nil dereference per render, with no message
|
||||||
|
panic(fmt.Sprintf("fakes: calc(%q) reached prep unparsed: %v", args[0], err))
|
||||||
|
}
|
||||||
at := make(map[string]int)
|
at := make(map[string]int)
|
||||||
for i, name := range calcVars(expr) {
|
for i, name := range calcVars(expr) {
|
||||||
at[name] = i
|
at[name] = i
|
||||||
|
|||||||
Reference in New Issue
Block a user