Skip to content

Commit

Permalink
CFStringRef#stringValue buffer needs space for 4 UTF8 bytes (#1345)
Browse files Browse the repository at this point in the history
  • Loading branch information
dbwiddis authored Apr 25, 2021
1 parent 5ac6161 commit 402d4c5
Show file tree
Hide file tree
Showing 3 changed files with 13 additions and 12 deletions.
2 changes: 1 addition & 1 deletion CHANGES.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ Features

Bug Fixes
---------
* [#1343](https://github.com/java-native-access/jna/issues/1343): `c.s.j.p.mac.CoreFoundation.CFStringRef#stringValue` buffer needs space for null byte - [@dbwiddis](https://github.com/dbwiddis).
* [#1343](https://github.com/java-native-access/jna/issues/1343), [#1345](https://github.com/java-native-access/jna/issues/1345): `c.s.j.p.mac.CoreFoundation.CFStringRef#stringValue` buffer needs space for 4 UTF8 bytes plus a null byte - [@dbwiddis](https://github.com/dbwiddis).

Release 5.8.0
=============
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2019 Daniel Widdis
* Copyright (c) 2019, 2021 Daniel Widdis
*
* The contents of this file is dual-licensed under 2
* alternative Open Source/Free licenses: LGPL 2.1 or later and
Expand Down Expand Up @@ -488,18 +488,19 @@ public static CFStringRef createCFString(String s) {
*/
public String stringValue() {
// Get number of characters
CFIndex length = INSTANCE.CFStringGetLength(this);
if (length.longValue() == 0) {
long length = INSTANCE.CFStringGetLength(this).longValue();
if (length == 0) {
return "";
}
// Calculate maximum possible size in UTF8 bytes
CFIndex maxSize = INSTANCE.CFStringGetMaximumSizeForEncoding(length, kCFStringEncodingUTF8);
if (maxSize.intValue() == kCFNotFound) {
// the CFStringGetMaximumSizeForEncoding function incorrectly returns 3 bytes
// per character so we'll use 4 bytes plus a null byte
if (length > (Long.MAX_VALUE - 1) / 4) {
throw new StringIndexOutOfBoundsException("CFString maximum number of bytes exceeds LONG_MAX.");
}
// Increment size by 1 for a null byte
maxSize.setValue(maxSize.longValue() + 1);
Memory buf = new Memory(maxSize.longValue());
long bufSize = 4 * length + 1;
CFIndex maxSize = new CFIndex(bufSize);
Memory buf = new Memory(bufSize);
if (0 != INSTANCE.CFStringGetCString(this, buf, maxSize, kCFStringEncodingUTF8)) {
return buf.getString(0, "UTF8");
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -63,9 +63,9 @@ public class CoreFoundationTest {

@Test
public void testCFStringRef() throws UnsupportedEncodingException {
// Create a unicode string of a single 3-byte character
byte[] alaf = { (byte) 0xe0, (byte) 0xa0, (byte) 0x80 };
String utf8Str = new String(alaf, StandardCharsets.UTF_8);
// Create a unicode string of a single 4-byte character
byte[] smileEmoji = { (byte) 0xF0, (byte) 0x9F, (byte) 0x98, (byte) 0x83 };
String utf8Str = new String(smileEmoji, StandardCharsets.UTF_8);
CFStringRef cfStr = CFStringRef.createCFString(utf8Str);
assertEquals(utf8Str.length(), CF.CFStringGetLength(cfStr).intValue());
assertEquals(utf8Str, cfStr.stringValue());
Expand Down

0 comments on commit 402d4c5

Please sign in to comment.