PlanByID pasted its id into the query, and the id comes from a caller of the plans verb: an id holding a quote changed the query (x' or '1'='1 answered another plan). The id is now $1, and RecentPlans's limit too, so no plan query is built from a value.
46 lines
1.7 KiB
Go
46 lines
1.7 KiB
Go
package inventory
|
|
|
|
import (
|
|
"strings"
|
|
"testing"
|
|
"time"
|
|
)
|
|
|
|
// **A plan's id is a value, never SQL** (novox/hq issue 561): the id reaches PlanByID from a caller of the
|
|
// controller's plans verb, so an id holding a quote is read as a plain id — no error from the store, and no
|
|
// other plan answered for it.
|
|
func TestAPlanIdHoldingAQuoteIsReadAsAPlainId(t *testing.T) {
|
|
inv := ForTest(t)
|
|
ctx := t.Context()
|
|
p := Plan{ID: "plan-561", Repository: "novox/mesh-controller", Commit: "abc", Created: time.Now().UTC(),
|
|
State: PlanBuilding, Tiers: [][]string{{"a"}}, Modules: map[string]*PlanModule{"a": {}}}
|
|
if err := inv.SavePlan(ctx, &p); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
for _, id := range []string{
|
|
"x' or '1'='1", // every plan, when pasted into the query
|
|
"plan-561' or id like '%", // the plan above, by a pattern
|
|
"it's", // a quote alone: a syntax error, when pasted
|
|
} {
|
|
got, err := inv.PlanByID(ctx, id)
|
|
if err == nil {
|
|
t.Fatalf("PlanByID(%q) answered %s, a plan of another id", id, got.ID)
|
|
}
|
|
if want := "no plan " + id; err.Error() != want {
|
|
t.Fatalf("PlanByID(%q) failed with %q, not as a plain id no plan has (%q)", id, err, want)
|
|
}
|
|
}
|
|
// A plan whose id holds a quote is found by it, and by nothing else.
|
|
quoted := p
|
|
quoted.ID, quoted.Revision = "plan-'561'", 0
|
|
if err := inv.SavePlan(ctx, "ed); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if got, err := inv.PlanByID(ctx, quoted.ID); err != nil || got.ID != quoted.ID {
|
|
t.Fatalf("the plan with a quote in its id was not read back: %v %+v", err, got.ID)
|
|
}
|
|
if recent, err := inv.RecentPlans(ctx, 1); err != nil || len(recent) != 1 || !strings.HasPrefix(recent[0].ID, "plan-") {
|
|
t.Fatalf("RecentPlans with a parameter: %v %+v", err, recent)
|
|
}
|
|
}
|