Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Servers incorrectly accept any request body when the modeled operation input is empty or non-existent #3723

Open
david-perez opened this issue Jun 27, 2024 · 0 comments
Labels
bug Something isn't working good first issue Good for newcomers server Rust server SDK

Comments

@david-perez
Copy link
Contributor

When there is operation input:

$version: "2.0"

namespace com.amazonaws.simple

use aws.protocols#restJson1
use smithy.test#httpMalformedRequestTests

@restJson1
service SimpleService {
    operations: [
        Operation
    ]
}

@http(uri: "/operation", method: "POST")
operation Operation {
    input: OperationInputOutput
    output: OperationInputOutput
}

structure OperationInputOutput {
    message: String
}

servers correctly reject a request that contains additional tokens past where we expect the end of the body:

apply Operation @httpMalformedRequestTests([
    {
        id: "AdditionalTokensEmptyStruct"
        documentation: """
        When additional tokens are found past where we expect the end of the body,
        the request should be rejected with a serialization exception."""
        protocol: restJson1
        request: {
            method: "POST"
            uri: "/operation"
            headers: {
                "Content-Type": "application/json"
            }
            body: "{}{}"
        },
        response: {
            headers: {
                "x-amzn-errortype": "SerializationException"
            }
            code: 400,
        }
    }
])

That is because JsonParserGenerator.kt asserts that there are no leftover tokens after parsing the operation input:

private fun RustWriter.expectEndOfTokenStream() {
rustBlock("if tokens.next().is_some()") {
rustTemplate(
"return Err(#{Error}::custom(\"found more JSON tokens after completing parsing\"));",
*codegenScope,
)
}
}

However, when the modeled operation input is empty:

structure OperationInputOutput { }

Or when there is no operation input (removing the Content-Type header in this case):

@http(uri: "/operation", method: "POST")
operation Operation { }

We don't generate a deserializer for the operation, and so we don't even attempt to inspect the body, accepting anything:

thread 'operation::operation_test::additional_tokens_empty_struct_malformed_request' panicked at simple/rust-server-codegen/src/operation.rs:112:52:
request should have been rejected, but we accepted it; we parsed operation input `OperationInput`

This bug affects all protocols. Note that in some protocols, like restJson1 and rpcv2Cbor (and perhaps all?), servers must accept both no request body and empty object in request body when the modeled operation input is empty. However, they shouldn't accept anything.

@david-perez david-perez added bug Something isn't working server Rust server SDK labels Jun 27, 2024
@david-perez david-perez added the good first issue Good for newcomers label Jun 28, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working good first issue Good for newcomers server Rust server SDK
Projects
None yet
Development

No branches or pull requests

1 participant