Skip to content

UCRT64: LC_NUMERIC changes after unformatted stream read on non-dot-decimal locales #29825

@Baljak

Description

@Baljak

Description / Steps to reproduce the issue

With MinGW-w64 UCRT builds of gfortran/libgfortran on Windows, an unformatted ACCESS='STREAM' read can change the process LC_NUMERIC from C to the Windows user locale. This bug does not occur on MinGW-w64 MSVCRT versions.

On Windows systems whose numeric locale is not dot-based, for example French Windows where LC_NUMERIC becomes French_France.1252, subsequent formatted/list-directed Fortran reads of dot-decimal real numbers are silently misparsed.

Examples:

  • "7.999999e-05" is read as 7
  • "0.202" is read as 0
  • "1.05" is read as 1

No read error is reported.

Steps to reproduce

A standalone reproducer is provided:

ucrt_locale_issue.f90
stream_probe.bin

ucrt_locale_issue.zip

It does not use any external dependency. It only:

  1. Parses a dot-decimal real from a character string.
  2. Performs one unformatted stream read from stream_probe.bin.
  3. Parses the same dot-decimal real again.
  4. Calls setlocale(LC_NUMERIC, "C") as a workaround.
  5. Parses again.

Workaround

Calling:

setlocale(LC_NUMERIC, "C");

after the unformatted stream read restores correct behavior.

Notes

This is only visible on Windows systems whose user numeric locale is not dot-based. On English/dot-decimal systems, the locale change may occur but does not break dot-decimal parsing.

Expected behavior

An unformatted stream read should not change the process LC_NUMERIC.

Formatted/list-directed Fortran reads of dot-decimal real values should continue to parse correctly, especially when the input uses standard scientific notation with . as the decimal separator.

Actual behavior

On a French Windows system:

lc_numeric  initial                   =  C
parse       initial                   =  0.8000
lc_numeric  after stream read         =  French_France.1252
parse       after stream read         =  7.0000
lc_numeric  after setlocale c         =  C
parse       after setlocale c         =  0.8000
lc_numeric  after more stream reads   =  C
parse       after more stream reads   =  0.8000

The important part is:

lc_numeric  after stream read         =  French_France.1252
parse       after stream read         =  7.0000

The real value should be 0.8000, but after the stream read it is parsed as 7.0000.

Verification

Windows Version

MINGW64_NT-10.0-26200

MINGW environments affected

  • MINGW64
  • MINGW32
  • UCRT64
  • CLANG64
  • CLANGARM64

Are you willing to submit a PR?

No response

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions