Skip to content

Invalid JSON desearilaztion beyond buffer end #183

@ayavilevich

Description

@ayavilevich

Platform

ESP32

IDE / Tooling

PlatformIO

What happened?

When calling the JSON handler with a scalar (number) the parsing fails and the handler returns a "HTTP/1.1 400 Bad Request" response instead of parsing the JSON correctly.

The curl command: curl -v -X POST -H 'Content-Type: application/json' -d '5' http://192.168.4.1/json2

Cause
AsyncCallbackJsonWebHandler class in AsyncJson.cpp will deserialize the body by using deserializeJson function of ArduinoJson. That function expects a null terminated string or the length of the data in the buffer as a third parameter. Instead, the caller passes a non null terminated buffer without a length parameter.

Reference
Proposed fix has been described here: me-no-dev#807
P.S. I will attempt a PR for the fix.
Discussion here: #182

With the fix described above, the issue is resolved.

Worth to note that there could be other unexpected behavior to this issue, including security issues, depending on the content that follows the buffer. This is however a re-producible case.

Stack Trace

curl result:

curl -v -X POST -H "Content-Type: application/json" -d "5" http://192.168.4.1/json2
Note: Unnecessary use of -X or --request, POST is already inferred.
*   Trying xxx
* Connected to xxx port 80
> POST /json2 HTTP/1.1
> Host: xxxx
> User-Agent: curl/8.9.1
> Accept: */*
> Content-Type: application/json
> Content-Length: 1
>
* upload completely sent off: 1 bytes
< HTTP/1.1 400 Bad Request
< connection: close
< accept-ranges: none
< content-length: 0
<
* shutting down connection #

Nothing appears in ESP32 serial output because the handler blocks the response from getting to the main code.


With the fix described in original issue 807 applied:

curl result:

C:\Users\arik>curl -v -X POST -H "Content-Type: application/json" -d "5" http://192.168.4.1/json2
Note: Unnecessary use of -X or --request, POST is already inferred.
*   Trying xxxxx
* Connected to xxxx port 80
> POST /json2 HTTP/1.1
> Host: xxxx
> User-Agent: curl/8.9.1
> Accept: */*
> Content-Type: application/json
> Content-Length: 1
>
* upload completely sent off: 1 bytes
< HTTP/1.1 200 OK
< connection: close
< accept-ranges: none
< content-length: 3
< content-type: text/plain
<
int* shutting down connection #0

ESP32 serial

12:01:59.418 > . Json:
12:04:39.267 > 5
12:04:39.267 > Got an int

Minimal Reproductible Example (MRE)

// based on https://github.com/ESP32Async/ESPAsyncWebServer/blob/main/examples/Json/Json.ino
// SPDX-License-Identifier: LGPL-3.0-or-later
// Copyright 2016-2025 Hristo Gochkov, Mathieu Carbou, Emil Muratov

#include <Arduino.h>
#include <AsyncTCP.h>
#include <WiFi.h>

#include <ESPAsyncWebServer.h>

#include <ArduinoJson.h>
#include <AsyncJson.h>
#include <AsyncMessagePack.h>

static AsyncWebServer server(80);

static AsyncCallbackJsonWebHandler *handler = new AsyncCallbackJsonWebHandler("/json2");

void setup()
{
  Serial.begin(115200);

  // setup wifi
  // AP
  // WiFi.mode(WIFI_AP);
  // WiFi.softAP("esp-captive");
  // client
  WiFi.mode(WIFI_STA); // for STA mode
  WiFi.begin("x", "y");
  while (WiFi.status() != WL_CONNECTED)
  {
    Serial.print(". ");
    delay(500);
  }

  // test cases
  // curl -v -X POST -H 'Content-Type: application/json' -d '{' http://192.168.4.1/json2
  // curl -v -X POST -H 'Content-Type: application/json' -d '5' http://192.168.4.1/json2
  handler->setMethod(HTTP_POST);
  handler->onRequest([](AsyncWebServerRequest *request, JsonVariant &json)
                     {
    Serial.println("Json:");
    serializeJson(json, Serial);
    Serial.println();
    if(json.is<int>())
    {
      Serial.println("Got an int");
    }
    // response
    request->send(200, "text/plain", json.is<int>() ? "int" : "not int"); });

  server.addHandler(handler);

  server.begin();
}

// not needed
void loop()
{
  delay(100);
}

I confirm that:

  • I have read the documentation.
  • I have searched for similar discussions.
  • I have searched for similar issues.
  • I have looked at the examples.
  • I have upgraded to the lasted version of ESPAsyncWebServer (and AsyncTCP for ESP32).

Metadata

Metadata

Labels

Type: BugSomething isn't working

Type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions