DynamoDB - error when sending an integer as string (#5108)

This commit is contained in:
Bert Blommers 2022-05-09 13:01:31 +00:00 committed by GitHub
parent 4a5c72d5ed
commit ff767d0743
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 49 additions and 1 deletions

View File

@ -310,3 +310,9 @@ class StreamAlreadyEnabledException(JsonRESTError):
def __init__(self):
er = "com.amazonaws.dynamodb.v20111205#ResourceInUseException"
super().__init__(er, "Cannot enable stream")
class InvalidConversion(JsonRESTError):
def __init__(self):
er = "SerializationException"
super().__init__(er, "NUMBER_VALUE cannot be converted to String")

View File

@ -33,6 +33,7 @@ from moto.dynamodb.exceptions import (
ResourceInUseException,
StreamAlreadyEnabledException,
MockValidationException,
InvalidConversion,
)
from moto.dynamodb.models.utilities import bytesize
from moto.dynamodb.models.dynamo_type import DynamoType
@ -646,6 +647,13 @@ class Table(CloudFormationModel):
if DynamoType(range_value).size() > RANGE_KEY_MAX_LENGTH:
raise RangeKeyTooLong
def _validate_item_types(self, item_attrs):
for key, value in item_attrs.items():
if type(value) == dict:
self._validate_item_types(value)
elif type(value) == int and key == "N":
raise InvalidConversion
def put_item(
self,
item_attrs,
@ -688,6 +696,8 @@ class Table(CloudFormationModel):
self._validate_key_sizes(item_attrs)
self._validate_item_types(item_attrs)
if expected is None:
expected = {}
lookup_range_value = range_value

View File

@ -1,9 +1,11 @@
import boto3
import botocore
import pytest
import sure # noqa # pylint: disable=unused-import
from boto3.dynamodb.conditions import Key
from botocore.exceptions import ClientError
from moto import mock_dynamodb
from unittest import SkipTest
from moto import mock_dynamodb, settings
table_schema = {
"KeySchema": [{"AttributeName": "partitionKey", "KeyType": "HASH"}],
@ -547,3 +549,33 @@ def test_update_item_non_existent_table():
err = exc.value.response["Error"]
assert err["Code"].should.equal("ResourceNotFoundException")
assert err["Message"].should.equal("Requested resource not found")
@mock_dynamodb
def test_put_item_wrong_datatype():
if settings.TEST_SERVER_MODE:
raise SkipTest("Unable to mock a session with Config in ServerMode")
session = botocore.session.Session()
config = botocore.client.Config(parameter_validation=False)
client = session.create_client("dynamodb", region_name="us-east-1", config=config)
client.create_table(
TableName="test2",
KeySchema=[{"AttributeName": "mykey", "KeyType": "HASH"}],
AttributeDefinitions=[{"AttributeName": "mykey", "AttributeType": "N"}],
BillingMode="PAY_PER_REQUEST",
)
with pytest.raises(ClientError) as exc:
client.put_item(TableName="test2", Item={"mykey": {"N": 123}})
err = exc.value.response["Error"]
err["Code"].should.equal("SerializationException")
err["Message"].should.equal("NUMBER_VALUE cannot be converted to String")
# Same thing - but with a non-key, and nested
with pytest.raises(ClientError) as exc:
client.put_item(
TableName="test2",
Item={"mykey": {"N": "123"}, "nested": {"M": {"sth": {"N": 5}}}},
)
err = exc.value.response["Error"]
err["Code"].should.equal("SerializationException")
err["Message"].should.equal("NUMBER_VALUE cannot be converted to String")