@@ -19,6 +19,7 @@ module DynamoDBSupport {
19
19
import opened Wrappers
20
20
import opened StandardLibrary
21
21
import opened StandardLibrary. UInt
22
+ import opened StandardLibrary. MemoryMath
22
23
import opened DynamoDbEncryptionUtil
23
24
import opened DdbVirtualFields
24
25
import opened SearchableEncryptionInfo
@@ -33,23 +34,30 @@ module DynamoDBSupport {
33
34
// At the moment, this means that no attribute names starts with "aws_dbe_",
34
35
// as all other attribute names would need to be configured, and all the
35
36
// other weird constraints were checked at configuration time.
36
- function method IsWriteable (item : DDB .AttributeMap)
37
- : (ret : Result< bool , string > )
37
+ method IsWriteable (item : DDB .AttributeMap)
38
+ returns (ret : Result< bool , string > )
38
39
// = specification/dynamodb-encryption-client/ddb-support.md#writable
39
40
// = type=implication
40
41
// # Writeable MUST reject any item containing an attribute which begins with `aws_dbe_`.
41
42
ensures ret. Success? ==> forall k < - item :: ! (ReservedPrefix <= k)
42
43
{
43
- if forall k < - item :: ! (ReservedPrefix <= k) then
44
- Success (true)
45
- else
46
- var bad := set k < - item | ReservedPrefix <= k;
47
- // We happen to order these values, but this ordering MUST NOT be relied upon.
48
- var badSeq := SortedSets. ComputeSetToOrderedSequence2 (bad, CharLess);
49
- if |badSeq| == 0 then
50
- Failure ("")
51
- else
52
- Failure ("Writing reserved attributes not allowed : " + Join(badSeq, "\n"))
44
+ var keys := SortedSets. ComputeSetToOrderedSequence2 (item.Keys, CharLess);
45
+ SequenceIsSafeBecauseItIsInMemory (keys);
46
+ var rp := ReservedPrefix; // because the constant ReservedPrefix is actual an expensive function call
47
+ for i : uint64 := 0 to |keys| as uint64
48
+ invariant forall j | 0 <= j < i :: ! (ReservedPrefix <= keys[j])
49
+ {
50
+ if rp <= keys[i] {
51
+ var result := "Writing reserved attributes not allowed : ";
52
+ for j : uint64 := i to |keys| as uint64 {
53
+ if rp <= keys[i] {
54
+ result := result + keys[i] + "\n";
55
+ }
56
+ }
57
+ return Failure (result);
58
+ }
59
+ }
60
+ return Success (true);
53
61
}
54
62
55
63
function method GetEncryptedAttributes (
@@ -83,7 +91,8 @@ module DynamoDBSupport {
83
91
{
84
92
if expr. Some? then
85
93
var attrs := GetEncryptedAttributes (actions, expr, attrNames);
86
- if |attrs| == 0 then
94
+ SequenceIsSafeBecauseItIsInMemory (attrs);
95
+ if |attrs| as uint64 == 0 then
87
96
Success (true)
88
97
else
89
98
Failure ("Condition Expressions forbidden on encrypted attributes : " + Join(attrs, ","))
@@ -121,7 +130,8 @@ module DynamoDBSupport {
121
130
if expr. Some? then
122
131
var attrs := Update. ExtractAttributes (expr.value, attrNames);
123
132
var encryptedAttrs := Seq. Filter (s => IsSigned(actions, s), attrs);
124
- if |encryptedAttrs| == 0 then
133
+ SequenceIsSafeBecauseItIsInMemory (encryptedAttrs);
134
+ if |encryptedAttrs| as uint64 == 0 then
125
135
Success (true)
126
136
else
127
137
Failure ("Update Expressions forbidden on signed attributes : " + Join(encryptedAttrs, ","))
@@ -169,11 +179,13 @@ module DynamoDBSupport {
169
179
// # if the constructed compound beacon does not match
170
180
// # the existing attribute value AddSignedBeacons MUST fail.
171
181
var badAttrs := set k < - newAttrs | k in item && item[k] != newAttrs[k] :: k;
172
- :- Need (|badAttrs| == 0, E("Signed beacons have generated values different from supplied values."));
182
+ SetIsSafeBecauseItIsInMemory (badAttrs);
183
+ :- Need (|badAttrs| as uint64 == 0, E("Signed beacons have generated values different from supplied values."));
173
184
var version : DDB. AttributeMap := map [VersionTag := DS (" ")];
174
185
var both := newAttrs. Keys * item. Keys;
175
186
var bad := set k < - both | newAttrs[k] != item[k];
176
- if 0 < |bad| {
187
+ SetIsSafeBecauseItIsInMemory (bad);
188
+ if 0 < |bad| as uint64 {
177
189
// We happen to order these values, but this ordering MUST NOT be relied upon.
178
190
var badSeq := SortedSets. ComputeSetToOrderedSequence2 (bad, CharLess);
179
191
return Failure (E("Supplied Beacons do not match calculated beacons : " + Join(badSeq, ", ")));
@@ -254,7 +266,8 @@ module DynamoDBSupport {
254
266
req. FilterExpression,
255
267
req. ExpressionAttributeNames,
256
268
req. ExpressionAttributeValues);
257
- :- Need (|newItems| < INT32_MAX_LIMIT, DynamoDbEncryptionUtil.E("This is impossible."));
269
+ SequenceIsSafeBecauseItIsInMemory (newItems);
270
+ :- Need (|newItems| as uint64 < INT32_MAX_LIMIT as uint64, DynamoDbEncryptionUtil.E("This is impossible."));
258
271
var trimmedItems := Seq. Map (i => DoRemoveBeacons(i), newItems);
259
272
var count :=
260
273
if resp. Count. Some? then
@@ -323,7 +336,8 @@ module DynamoDBSupport {
323
336
req. FilterExpression,
324
337
req. ExpressionAttributeNames,
325
338
req. ExpressionAttributeValues);
326
- :- Need (|newItems| < INT32_MAX_LIMIT, DynamoDbEncryptionUtil.E("This is impossible."));
339
+ SequenceIsSafeBecauseItIsInMemory (newItems);
340
+ :- Need (|newItems| as uint64 < INT32_MAX_LIMIT as uint64, DynamoDbEncryptionUtil.E("This is impossible."));
327
341
var trimmedItems := Seq. Map (i => DoRemoveBeacons(i), newItems);
328
342
var count :=
329
343
if resp. Count. Some? then
@@ -344,14 +358,15 @@ module DynamoDBSupport {
344
358
requires forall x < - results :: x in bv. virtualFields
345
359
ensures output. Success? ==> forall x < - output. value :: x in bv. virtualFields
346
360
{
347
- if |fields| == 0 then
361
+ SequenceIsSafeBecauseItIsInMemory (fields);
362
+ if |fields| as uint64 == 0 then
348
363
Success (results)
349
364
else
350
- var optValue :- GetVirtField (bv.virtualFields[fields[0]], item);
365
+ var optValue :- GetVirtField (bv.virtualFields[fields[0 as uint32 ]], item);
351
366
if optValue. Some? then
352
- GetVirtualFieldsLoop (fields[1..], bv, item, results[fields[0] := optValue.value])
367
+ GetVirtualFieldsLoop (fields[1 as uint32 ..], bv, item, results[fields[0 as uint32 ] := optValue.value])
353
368
else
354
- GetVirtualFieldsLoop (fields[1..], bv, item, results)
369
+ GetVirtualFieldsLoop (fields[1 as uint32 ..], bv, item, results)
355
370
}
356
371
357
372
method GetVirtualFields (beaconVersion : SearchableEncryptionInfo .BeaconVersion, item : DDB .AttributeMap)
@@ -371,18 +386,19 @@ module DynamoDBSupport {
371
386
requires forall x < - results :: x in bv. beacons
372
387
ensures output. Success? ==> forall x < - output. value :: x in bv. beacons
373
388
{
374
- if |fields| == 0 then
389
+ SequenceIsSafeBecauseItIsInMemory (fields);
390
+ if |fields| as uint64 == 0 then
375
391
Success (results)
376
392
else
377
- var beacon := bv. beacons[fields[0]];
393
+ var beacon := bv. beacons[fields[0 as uint32 ]];
378
394
if beacon. Compound? then
379
395
var optValue :- beacon. cmp. getNaked (item, bv.virtualFields);
380
396
if optValue. Some? then
381
- GetCompoundBeaconsLoop (fields[1..], bv, item, results[fields[0] := optValue.value])
397
+ GetCompoundBeaconsLoop (fields[1 as uint32 ..], bv, item, results[fields[0] := optValue.value])
382
398
else
383
- GetCompoundBeaconsLoop (fields[1..], bv, item, results)
399
+ GetCompoundBeaconsLoop (fields[1 as uint32 ..], bv, item, results)
384
400
else
385
- GetCompoundBeaconsLoop (fields[1..], bv, item, results)
401
+ GetCompoundBeaconsLoop (fields[1 as uint32 ..], bv, item, results)
386
402
}
387
403
388
404
method GetCompoundBeacons (beaconVersion : SearchableEncryptionInfo .BeaconVersion, item : DDB .AttributeMap)
0 commit comments