Skip to content

Commit d5cb05d

Browse files
authored
Reject requests with predicates larger than the max size allowed. (#3052)
* Reject requests with predicates larger than the max size allowed. This change introduces checks in server.go to verify that Alter, Mutation, and Query requests that includes predicates larger than 2^16 characters are rejected before being processed. * Address review comments. * run go fmt
1 parent 3f97d96 commit d5cb05d

File tree

3 files changed

+103
-1
lines changed

3 files changed

+103
-1
lines changed

edgraph/server.go

+40-1
Original file line numberDiff line numberDiff line change
@@ -348,13 +348,17 @@ func (s *Server) Alter(ctx context.Context, op *api.Operation) (*api.Payload, er
348348
return empty, err
349349
}
350350

351-
// Reserved predicates cannot be altered.
352351
for _, update := range result.Schemas {
352+
// Reserved predicates cannot be altered.
353353
if x.IsReservedPredicate(update.Predicate) {
354354
err := fmt.Errorf("predicate %s is reserved and is not allowed to be modified",
355355
update.Predicate)
356356
return nil, err
357357
}
358+
359+
if err := validatePredName(update.Predicate); err != nil {
360+
return nil, err
361+
}
358362
}
359363

360364
glog.Infof("Got schema: %+v\n", result.Schemas)
@@ -560,6 +564,11 @@ func (s *Server) doQuery(ctx context.Context, req *api.Request) (resp *api.Respo
560564
if err != nil {
561565
return resp, err
562566
}
567+
568+
if err = validateQuery(parsedReq.Query); err != nil {
569+
return resp, err
570+
}
571+
563572
if req.StartTs == 0 {
564573
req.StartTs = State.getTimestamp(req.ReadOnly)
565574
}
@@ -769,6 +778,9 @@ func validateAndConvertFacets(nquads []*api.NQuad) error {
769778

770779
func validateNQuads(set, del []*api.NQuad) error {
771780
for _, nq := range set {
781+
if err := validatePredName(nq.Predicate); err != nil {
782+
return err
783+
}
772784
var ostar bool
773785
if o, ok := nq.ObjectValue.GetVal().(*api.Value_DefaultVal); ok {
774786
ostar = o.DefaultVal == x.Star
@@ -781,6 +793,9 @@ func validateNQuads(set, del []*api.NQuad) error {
781793
}
782794
}
783795
for _, nq := range del {
796+
if err := validatePredName(nq.Predicate); err != nil {
797+
return err
798+
}
784799
var ostar bool
785800
if o, ok := nq.ObjectValue.GetVal().(*api.Value_DefaultVal); ok {
786801
ostar = o.DefaultVal == x.Star
@@ -821,3 +836,27 @@ func validateKeys(nq *api.NQuad) error {
821836
}
822837
return nil
823838
}
839+
840+
// validateQuery verifies that the query does not contain any preds that
841+
// are longer than the limit (2^16).
842+
func validateQuery(queries []*gql.GraphQuery) error {
843+
for _, q := range queries {
844+
if err := validatePredName(q.Attr); err != nil {
845+
return err
846+
}
847+
848+
if err := validateQuery(q.Children); err != nil {
849+
return err
850+
}
851+
}
852+
853+
return nil
854+
}
855+
856+
func validatePredName(name string) error {
857+
if len(name) > math.MaxUint16 {
858+
return fmt.Errorf("Predicate name length cannot be bigger than 2^16. Predicate: %v",
859+
name[:80])
860+
}
861+
return nil
862+
}

query/query3_test.go

+25
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,8 @@ package query
1919
import (
2020
"context"
2121
"encoding/json"
22+
"fmt"
23+
"strings"
2224
"testing"
2325

2426
"github.com/stretchr/testify/require"
@@ -1949,3 +1951,26 @@ func TestMultipleTypeDirectivesInPredicate(t *testing.T) {
19491951
js := processQueryNoErr(t, query)
19501952
require.JSONEq(t, `{"data": {"me":[{"enemy":[{"name":"Margaret", "pet":[{"name":"Bear"}]}, {"name":"Leonard"}]}]}}`, js)
19511953
}
1954+
1955+
func TestMaxPredicateSize(t *testing.T) {
1956+
// Create a string that has more than than 2^16 chars.
1957+
var b strings.Builder
1958+
for i := 0; i < 10000; i++ {
1959+
b.WriteString("abcdefg")
1960+
}
1961+
largePred := b.String()
1962+
1963+
query := fmt.Sprintf(`
1964+
{
1965+
me(func: uid(0x2)) {
1966+
%s {
1967+
name
1968+
}
1969+
}
1970+
}
1971+
`, largePred)
1972+
1973+
_, err := processQuery(t, context.Background(), query)
1974+
require.Error(t, err)
1975+
require.Contains(t, err.Error(), "Predicate name length cannot be bigger than 2^16")
1976+
}

systest/mutations_test.go

+38
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,7 @@ func TestSystem(t *testing.T) {
7979
t.Run("has should not have deleted edge", wrap(HasDeletedEdge))
8080
t.Run("has should have reverse edges", wrap(HasReverseEdge))
8181
t.Run("facet json input supports anyofterms query", wrap(FacetJsonInputSupportsAnyOfTerms))
82+
t.Run("max predicate size", wrap(MaxPredicateSize))
8283
}
8384

8485
func FacetJsonInputSupportsAnyOfTerms(t *testing.T, c *dgo.Dgraph) {
@@ -1678,3 +1679,40 @@ func HasReverseEdge(t *testing.T, c *dgo.Dgraph) {
16781679
require.Equal(t, len(revs), 1)
16791680
require.Equal(t, revs[0].Name, "carol")
16801681
}
1682+
1683+
func MaxPredicateSize(t *testing.T, c *dgo.Dgraph) {
1684+
// Create a string that has more than than 2^16 chars.
1685+
var b strings.Builder
1686+
for i := 0; i < 10000; i++ {
1687+
b.WriteString("abcdefg")
1688+
}
1689+
largePred := b.String()
1690+
1691+
// Verify that Alter requests with predicates that are too large are rejected.
1692+
ctx := context.Background()
1693+
err := c.Alter(ctx, &api.Operation{
1694+
Schema: fmt.Sprintf(`%s: uid @reverse .`, largePred),
1695+
})
1696+
require.Error(t, err)
1697+
require.Contains(t, err.Error(), "Predicate name length cannot be bigger than 2^16")
1698+
1699+
// Verify that Mutate requests with predicates that are too large are rejected.
1700+
txn := c.NewTxn()
1701+
_, err = txn.Mutate(ctx, &api.Mutation{
1702+
CommitNow: true,
1703+
SetNquads: []byte(fmt.Sprintf(`_:test <%s> "value" .`, largePred)),
1704+
})
1705+
require.Error(t, err)
1706+
require.Contains(t, err.Error(), "Predicate name length cannot be bigger than 2^16")
1707+
_ = txn.Discard(ctx)
1708+
1709+
// Do the same thing as above but for the predicates in DelNquads.
1710+
txn = c.NewTxn()
1711+
defer txn.Discard(ctx)
1712+
_, err = txn.Mutate(ctx, &api.Mutation{
1713+
CommitNow: true,
1714+
DelNquads: []byte(fmt.Sprintf(`_:test <%s> "value" .`, largePred)),
1715+
})
1716+
require.Error(t, err)
1717+
require.Contains(t, err.Error(), "Predicate name length cannot be bigger than 2^16")
1718+
}

0 commit comments

Comments
 (0)