Skip to content

[Bug] Locale-sensitive case conversions break identifier matching, enum parsing and request signing #9770

Description

@LuciferYang

Bug description

String.toLowerCase() and String.toUpperCase() follow the JVM default locale. Under a Turkish or Azeri default, i uppercases to the dotted İ and I lowercases to the dotless ı, so any token that is case-folded before being matched, parsed or signed stops matching what it is compared against.

This started as an identifier-matching bug. With case-sensitive = false, CDC table mapping, computed columns and the Arrow readers all route through StringUtils.toLowerCaseIfNeed, and CdcRecord.fieldNameLowerCase is the record side of the same join, so a source column INDEX stops mapping to schema field index and the column silently nulls out.

Auditing the rest of paimon-api, paimon-common and paimon-core turned up the same conversion in places where it throws rather than mismatching quietly:

  • CoreOptions.partitionMarkDoneActions() does PartitionMarkDoneAction.valueOf(x.replace('-','_').toUpperCase()). Both success-file and done-partition contain an i, so under Turkish this throws IllegalArgumentException: No enum constant ...PartitionMarkDoneAction.SUCCESS_FİLE.
  • RowKind.fromShortString("+i") uppercases to , matches no case arm, and throws UnsupportedOperationException.
  • DistributedLockDialectFactory does JdbcProtocol.valueOf(protocol.toUpperCase()) and loses SQLITE and MARIADB, so JDBC catalog locking cannot resolve its dialect.
  • OperatingSystem lowercases os.name and then looks for solaris, which becomes solarıs, so the OS is reported as UNKNOWN.
  • The DLF request signers lowercase header names to build the signature, option key lookups and format identifiers lowercase user-supplied keys, and system table lookup lowercases the table name. All of these compare the result against a fixed ASCII string.

Expected behavior

None of these conversions should depend on the operator's locale: they are all machine-facing, so they should pin Locale.ROOT.

BinaryString.toLowerCase / toUpperCase are already safe: the ASCII path uses Character.toLowerCase and the non-ASCII fallback pins Locale.ROOT, so the SQL upper() / lower() transforms over user data are not affected.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions