bson_as_relaxed_extended_json and bson_as_canonical_extended_json emit commas instead of dots for doubles under decimal-comma locales (e.g., pt_BR.UTF-8), violating RFC 8259 Section 6.

XMLWordPrintableJSON

    • Type: Bug
    • Resolution: Unresolved
    • Priority: Trivial - P5
    • None
    • Affects Version/s: 2.2.3
    • Component/s: None
    • Not Needed
    • None
    • C Drivers
    • None
    • None
    • None
    • None
    • None
    • None

      Summary

      bson_as_relaxed_extended_json and bson_as_canonical_extended_json emit commas instead of dots for doubles under decimal-comma locales (e.g., pt_BR.UTF-8), violating RFC 8259 Section 6.

      Environment

      C / CXX driver version: libbson 2.3.1 (MongoDB C Driver)

      Host OS, version, and architecture: Distro: Linux Mint 21.1 Vera | Linux Kernel 5.15.0-186-generic #196-Ubuntu SMP Sat Jun 20 16:09:34 UTC 2026 x86_64 x86_64 x86_64 GNU/Linux

      C / CXX compiler and version: gcc (Ubuntu 11.4.0-1ubuntu1~22.04.3) 11.4.0

      CMake output: N/A (Tested against prebuilt/installed libbson)

      MongoDB server version and topology: N/A (Pure libbson JSON serialization issue)

      How to Reproduce

      Set the host process locale to a decimal-comma locale (e.g. `pt_BR.UTF-8`) using `setlocale(LC_ALL, "pt_BR.UTF-8")`, then convert a BSON object with a floating-point value to JSON using `bson_as_relaxed_extended_json`.

      Minimal Reproducible Example (PoC):

      ```c
      #include <bson/bson.h>
      #include <stdio.h>
      #include <locale.h>

      int main(int argc, char **argv)
      {
          if (setlocale(LC_ALL, "pt_BR.UTF-8") == NULL)

      {         printf("Unable to set locale\n");         return -1;     }

          bson_t *b = BCON_NEW("foo", BCON_DOUBLE(123.456));
          char *str = bson_as_relaxed_extended_json(b, NULL);
          
          printf("Result: %s\n", str);
          // Outputs: { "foo" : 123,45600000000000307 } (Invalid JSON - uses comma)
          // Expected: { "foo" : 123.45600000000000307 } (Valid RFC 8259 JSON - uses dot)

          bson_free(str);
          bson_destroy(b);
          return 0;
      }

      Additional Background

      The issue stems from `bson_vsnprintf` in `src/libbson/src/bson/bson-string.c`. It delegates numeric formatting directly to standard C library functions (`vsnprintf` on POSIX and `_vsnprintf_s` on MSVC):

      ```c
      int
      bson_vsnprintf(char *str, size_t size, const char *format, va_list ap)

      {     // ... #else     int r;     // ...     r = vsnprintf(str, size, format, ap); // Affected by global LC_NUMERIC     str[size - 1] = '\0';     return r; #endif }

      Since functions like bson_as_relaxed_extended_json rely on internal string formatting built on top of bson_vsnprintf, any non-C locale with decimal-commas causes vsnprintf to output commas instead of periods, producing invalid JSON strings that fail to parse downstream in JSON-compliant parsers (e.g., in Java or C# environments).

      Impact & Standard Compliance

      Functions generating standardized text formats must guarantee locale-independent formatting. libbson should ensure numeric conversions always use an invariant locale (e.g., via uselocale(), snprintf_l(), or a dedicated locale-independent float-to-string formatter like Ryu) regardless of the host environment's locale settings.

            Assignee:
            Unassigned
            Reporter:
            Fábio Pereira da Silva (EXT)
            Votes:
            0 Vote for this issue
            Watchers:
            4 Start watching this issue

              Created:
              Updated: