mirror of https://github.com/k3s-io/k3s
fix a client-go bug which could casue kubectl panic (#72952)
* When user try execute command like `kubectl get pod test -o custom-columns=CONTAINER:.spec.containers[-1].name` It will throw a panic about slice index out of bounds. This patch fix it. * add test casepull/564/head
parent
ef2a5b948b
commit
1e245fad87
|
@ -255,10 +255,9 @@ func (j *JSONPath) evalArray(input []reflect.Value, node *ArrayNode) ([]reflect.
|
|||
params[1].Value = value.Len()
|
||||
}
|
||||
|
||||
if params[1].Value < 0 {
|
||||
if params[1].Value < 0 || (params[1].Value == 0 && params[1].Derived) {
|
||||
params[1].Value += value.Len()
|
||||
}
|
||||
|
||||
sliceLength := value.Len()
|
||||
if params[1].Value != params[0].Value { // if you're requesting zero elements, allow it through.
|
||||
if params[0].Value >= sliceLength || params[0].Value < 0 {
|
||||
|
@ -267,6 +266,11 @@ func (j *JSONPath) evalArray(input []reflect.Value, node *ArrayNode) ([]reflect.
|
|||
if params[1].Value > sliceLength || params[1].Value < 0 {
|
||||
return input, fmt.Errorf("array index out of bounds: index %d, length %d", params[1].Value-1, sliceLength)
|
||||
}
|
||||
if params[0].Value > params[1].Value {
|
||||
return input, fmt.Errorf("starting index %d is greater than ending index %d", params[0].Value, params[1].Value)
|
||||
}
|
||||
} else {
|
||||
return result, nil
|
||||
}
|
||||
|
||||
if !params[2].Known {
|
||||
|
|
|
@ -369,3 +369,153 @@ func TestFilterPartialMatchesSometimesMissingAnnotations(t *testing.T) {
|
|||
t,
|
||||
)
|
||||
}
|
||||
|
||||
func TestNegativeIndex(t *testing.T) {
|
||||
var input = []byte(
|
||||
`{
|
||||
"apiVersion": "v1",
|
||||
"kind": "Pod",
|
||||
"spec": {
|
||||
"containers": [
|
||||
{
|
||||
"image": "radial/busyboxplus:curl",
|
||||
"name": "fake0"
|
||||
},
|
||||
{
|
||||
"image": "radial/busyboxplus:curl",
|
||||
"name": "fake1"
|
||||
},
|
||||
{
|
||||
"image": "radial/busyboxplus:curl",
|
||||
"name": "fake2"
|
||||
},
|
||||
{
|
||||
"image": "radial/busyboxplus:curl",
|
||||
"name": "fake3"
|
||||
}]}}`)
|
||||
|
||||
var data interface{}
|
||||
err := json.Unmarshal(input, &data)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
testJSONPath(
|
||||
[]jsonpathTest{
|
||||
{
|
||||
"test containers[0], it equals containers[0]",
|
||||
`{.spec.containers[0].name}`,
|
||||
data,
|
||||
"fake0",
|
||||
false,
|
||||
},
|
||||
{
|
||||
"test containers[0:0], it equals the empty set",
|
||||
`{.spec.containers[0:0].name}`,
|
||||
data,
|
||||
"",
|
||||
false,
|
||||
},
|
||||
{
|
||||
"test containers[0:-1], it equals containers[0:3]",
|
||||
`{.spec.containers[0:-1].name}`,
|
||||
data,
|
||||
"fake0 fake1 fake2",
|
||||
false,
|
||||
},
|
||||
{
|
||||
"test containers[-1:0], expect error",
|
||||
`{.spec.containers[-1:0].name}`,
|
||||
data,
|
||||
"",
|
||||
true,
|
||||
},
|
||||
{
|
||||
"test containers[-1], it equals containers[3]",
|
||||
`{.spec.containers[-1].name}`,
|
||||
data,
|
||||
"fake3",
|
||||
false,
|
||||
},
|
||||
{
|
||||
"test containers[-1:], it equals containers[3:]",
|
||||
`{.spec.containers[-1:].name}`,
|
||||
data,
|
||||
"fake3",
|
||||
false,
|
||||
},
|
||||
{
|
||||
"test containers[-2], it equals containers[2]",
|
||||
`{.spec.containers[-2].name}`,
|
||||
data,
|
||||
"fake2",
|
||||
false,
|
||||
},
|
||||
{
|
||||
"test containers[-2:], it equals containers[2:]",
|
||||
`{.spec.containers[-2:].name}`,
|
||||
data,
|
||||
"fake2 fake3",
|
||||
false,
|
||||
},
|
||||
{
|
||||
"test containers[-3], it equals containers[1]",
|
||||
`{.spec.containers[-3].name}`,
|
||||
data,
|
||||
"fake1",
|
||||
false,
|
||||
},
|
||||
{
|
||||
"test containers[-4], it equals containers[0]",
|
||||
`{.spec.containers[-4].name}`,
|
||||
data,
|
||||
"fake0",
|
||||
false,
|
||||
},
|
||||
{
|
||||
"test containers[-4:], it equals containers[0:]",
|
||||
`{.spec.containers[-4:].name}`,
|
||||
data,
|
||||
"fake0 fake1 fake2 fake3",
|
||||
false,
|
||||
},
|
||||
{
|
||||
"test containers[-5], expect a error cause it out of bounds",
|
||||
`{.spec.containers[-5].name}`,
|
||||
data,
|
||||
"",
|
||||
true, // expect error
|
||||
},
|
||||
{
|
||||
"test containers[5:5], expect empty set",
|
||||
`{.spec.containers[5:5].name}`,
|
||||
data,
|
||||
"",
|
||||
false,
|
||||
},
|
||||
{
|
||||
"test containers[-5:-5], expect empty set",
|
||||
`{.spec.containers[-5:-5].name}`,
|
||||
data,
|
||||
"",
|
||||
false,
|
||||
},
|
||||
{
|
||||
"test containers[3:1], expect a error cause start index is greater than end index",
|
||||
`{.spec.containers[3:1].name}`,
|
||||
data,
|
||||
"",
|
||||
true,
|
||||
},
|
||||
{
|
||||
"test containers[-1:-2], it equals containers[3:2], expect a error cause start index is greater than end index",
|
||||
`{.spec.containers[-1:-2].name}`,
|
||||
data,
|
||||
"",
|
||||
true,
|
||||
},
|
||||
},
|
||||
false,
|
||||
t,
|
||||
)
|
||||
}
|
||||
|
|
|
@ -130,8 +130,9 @@ func (f *IdentifierNode) String() string {
|
|||
|
||||
// ParamsEntry holds param information for ArrayNode
|
||||
type ParamsEntry struct {
|
||||
Value int
|
||||
Known bool // whether the value is known when parse it
|
||||
Value int
|
||||
Known bool // whether the value is known when parse it
|
||||
Derived bool
|
||||
}
|
||||
|
||||
// ArrayNode holds start, end, step information for array index selection
|
||||
|
|
|
@ -325,6 +325,7 @@ Loop:
|
|||
if i == 1 {
|
||||
params[i].Known = true
|
||||
params[i].Value = params[0].Value + 1
|
||||
params[i].Derived = true
|
||||
} else {
|
||||
params[i].Known = false
|
||||
params[i].Value = 0
|
||||
|
|
|
@ -35,10 +35,10 @@ var parserTests = []parserTest{
|
|||
[]Node{newText("hello "), newList(), newField("jsonpath")}, false},
|
||||
{"quote", `{"{"}`, []Node{newList(), newText("{")}, false},
|
||||
{"array", `{[1:3]}`, []Node{newList(),
|
||||
newArray([3]ParamsEntry{{1, true}, {3, true}, {0, false}})}, false},
|
||||
newArray([3]ParamsEntry{{1, true, false}, {3, true, false}, {0, false, false}})}, false},
|
||||
{"allarray", `{.book[*].author}`,
|
||||
[]Node{newList(), newField("book"),
|
||||
newArray([3]ParamsEntry{{0, false}, {0, false}, {0, false}}), newField("author")}, false},
|
||||
newArray([3]ParamsEntry{{0, false, false}, {0, false, false}, {0, false, false}}), newField("author")}, false},
|
||||
{"wildcard", `{.bicycle.*}`,
|
||||
[]Node{newList(), newField("bicycle"), newWildcard()}, false},
|
||||
{"filter", `{[?(@.price<3)]}`,
|
||||
|
@ -52,7 +52,7 @@ var parserTests = []parserTest{
|
|||
}, false},
|
||||
{"union", `{['bicycle.price', 3, 'book.price']}`, []Node{newList(), newUnion([]*ListNode{}),
|
||||
newList(), newField("bicycle"), newField("price"),
|
||||
newList(), newArray([3]ParamsEntry{{3, true}, {4, true}, {0, false}}),
|
||||
newList(), newArray([3]ParamsEntry{{3, true, false}, {4, true, true}, {0, false, false}}),
|
||||
newList(), newField("book"), newField("price"),
|
||||
}, false},
|
||||
{"range", `{range .items}{.name},{end}`, []Node{
|
||||
|
@ -77,6 +77,12 @@ var parserTests = []parserTest{
|
|||
[]Node{newList(), newFilter(newList(), newList(), "=="), newList(), newField("status"), newField("nodeInfo"), newField("osImage"), newList(), newText("\"\"")}, false},
|
||||
{"single containing escaped single", `{[?(@.status.nodeInfo.osImage == '\\\'')]}`,
|
||||
[]Node{newList(), newFilter(newList(), newList(), "=="), newList(), newField("status"), newField("nodeInfo"), newField("osImage"), newList(), newText("\\'")}, false},
|
||||
{"negative index slice, equals a[len-5] to a[len-1]", `{[-5:]}`, []Node{newList(),
|
||||
newArray([3]ParamsEntry{{-5, true, false}, {0, false, false}, {0, false, false}})}, false},
|
||||
{"negative index slice, equals a[len-1]", `{[-1]}`, []Node{newList(),
|
||||
newArray([3]ParamsEntry{{-1, true, false}, {0, true, true}, {0, false, false}})}, false},
|
||||
{"negative index slice, equals a[1] to a[len-1]", `{[1:-1]}`, []Node{newList(),
|
||||
newArray([3]ParamsEntry{{1, true, false}, {-1, true, false}, {0, false, false}})}, false},
|
||||
}
|
||||
|
||||
func collectNode(nodes []Node, cur Node) []Node {
|
||||
|
|
Loading…
Reference in New Issue