Skip to content

[4.0] SR-5640: JSONEncoder misrepresents UInt.max #1196

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

Merged

Conversation

ianpartridge
Copy link
Contributor

Cherry-pick of #1173 to swift-4.0-branch.

@ianpartridge
Copy link
Contributor Author

@swift-ci please test

@ianpartridge ianpartridge requested a review from parkera September 6, 2017 13:13
@parkera
Copy link
Contributor

parkera commented Sep 6, 2017

I think we're still waiting on an official tag for swift-4.0 before we continue to make fixes on this branch.

@ianpartridge
Copy link
Contributor Author

Reopening to get this into the 4.0 branch.

@ianpartridge ianpartridge reopened this Oct 6, 2017
@ianpartridge
Copy link
Contributor Author

@swift-ci please test

This is a workaround rather than a full fix.

- NSNumber(value: UInt.max).stringValue was returning "-1"
  instead of "18446744073709551615" because NSNumber holds any
  value > Int64.max as a 128Bit quantity using a high Int and
  low UInt. It marks this type as an 'SInt128Type'.

- CFNumberFormatterCreateStringWithNumber() uses CFNumberGetType()
  to get this type however CoreFoundation wants to hide SInt128Type
  (probably for backwards compatibilty) and instead returns it
  as an SInt64Type. Thus only the low part of the NSNumber is used
  for the number and this is interpreted as an Int64.

- The workaround is simply in NSNumber.description(withLocale:)
  to test to see if the value is of type SInt128Type and if so
  use String(format: "%@") to convert it to a string instead of
  using CFNumberFormatterCreateStringWithNumber(). This should be
  ok for most situations since it is only used for positive
  integers and there are no issues with formatting leading zeros
  or decimal points.

- For JSONWriter._serializationString(for: NSNumber) the value
  is tested to see if it is not a floating point value and if so
  the .stringValue method is used to create a string.

- NSNumber.description(withLocale:) - cache the CFNumberFormatter
  when locale is nil as a small speedup.
@ianpartridge ianpartridge force-pushed the jsonencoder-uintmax-4.0 branch from ea09499 to feb2950 Compare October 6, 2017 12:09
@ianpartridge
Copy link
Contributor Author

@swift-ci please test

@ianpartridge
Copy link
Contributor Author

@swift-ci please test and merge

@swift-ci swift-ci merged commit ae9c3c5 into swiftlang:swift-4.0-branch Oct 9, 2017
@ianpartridge ianpartridge deleted the jsonencoder-uintmax-4.0 branch October 10, 2017 14:04
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants