java-native-access/jna · error · StringIndexOutOfBoundsException
CFString maximum number of bytes exceeds LONG_MAX.
Error message
CFString maximum number of bytes exceeds LONG_MAX.
What it means
stringValue() computes the UTF-8 buffer size via CFStringGetMaximumSizeForEncoding; if the native function reports kCFNotFound (-1), the required size exceeds LONG_MAX and the method throws StringIndexOutOfBoundsException. This effectively only occurs with absurdly large or corrupted CFString lengths.
Solutions
- Verify the pointer is a valid CFString (isTypeID(STRING_TYPE_ID)) before calling stringValue(); corrupt pointers are the usual cause.
- Wrap stringValue() in try-catch for StringIndexOutOfBoundsException and fall back to an alternate conversion or empty string.
- Re-acquire the string from the source API instead of reusing a possibly-released CFString reference.
- If legitimate huge strings are expected, chunk them at the source rather than converting in one call.
Example fix
// before
String s = cfStringRef.stringValue(); // may throw StringIndexOutOfBoundsException
// after
String s;
try {
s = cfStringRef.stringValue();
} catch (StringIndexOutOfBoundsException e) {
s = ""; // invalid/oversized CFString, fall back
} Defensive patterns
Strategy: try-catch
Validate before calling
CFTypeRef ref = new CFTypeRef(ptr); if (!ref.isTypeID(CoreFoundation.STRING_TYPE_ID)) return null; // not a valid CFString if (ptr == null) return null;
Type guard
boolean isUsableCFString(Pointer p) {
return p != null && new CFTypeRef(p).isTypeID(CoreFoundation.STRING_TYPE_ID);
} Try / catch
try {
String s = cfStringRef.stringValue();
} catch (StringIndexOutOfBoundsException e) {
String s = ""; // corrupted or oversized CFString
} Prevention
- Validate the pointer is a genuine CFString before calling stringValue()
- Do not reuse CFString references after CFRelease — released memory can report corrupt lengths
- Treat StringIndexOutOfBoundsException here as a corruption signal, not a size problem
- Keep references alive (retain) while converting strings from Get-function results
When it happens
Trigger: Calling CFStringRef.stringValue() (directly or via getStringProperty/getLocaleDateTimeFormat etc.) on a CFString whose reported length, multiplied for UTF-8 encoding, overflows CFIndex, or on a corrupt/forged CFString pointer.
Common situations: Wrapping garbage pointers as CFStringRef so CFStringGetLength returns nonsense; OS API changes returning malformed strings; strings longer than CFIndex can represent (practically never for legitimate data).
Understand the failure class
Background: "value must be between 0 and 1" / "out of range" / "must not be negative" errors: fixing range-validation failures across open-source libraries — this error's family across 42 libraries.
Related errors
- CFString conversion fails or the provided buffer is too…
- Unable to cast to CFArray. Type ID
- Unable to cast to CFBoolean. Type ID
- Unable to cast to CFData. Type ID
- Unable to cast to CFDictionary. Type ID
AI-assisted analysis of java-native-access/jna@d036ad9781 (2026-09-12).
Data as JSON: /api/errors/ff95de45f8059d65.
Report an issue: GitHub.
Appendix: source
Thrown at contrib/platform/src/com/sun/jna/platform/mac/CoreFoundation.java:580
/**
* Convert a reference to a Core Foundations String into its
* {@link java.lang.String}
*
* @return The corresponding {@link java.lang.String}, or null if the conversion
* failed.
*/
public String stringValue() {
// Get number of characters (UTF-16 code pairs)
// Code points > 0xffff will have 2 characters per Unicode character
CFIndex length = INSTANCE.CFStringGetLength(this);
if (length.longValue() == 0) {
return "";
}
// Calculate maximum possible size in UTF8 bytes
// This will be 3 x length
CFIndex maxSize = INSTANCE.CFStringGetMaximumSizeForEncoding(length, kCFStringEncodingUTF8);
if (maxSize.intValue() == kCFNotFound) {
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());
if (0 != INSTANCE.CFStringGetCString(this, buf, maxSize, kCFStringEncodingUTF8)) {
return buf.getString(0, "UTF8");
}
throw new IllegalArgumentException("CFString conversion fails or the provided buffer is too small.");
}
}
/**
* A wrapper for the {@link NativeLong} type, used for {@link CFNumberRef}
* types, {@link CFStringRef} lengths, and {@link CFArrayRef} sizes and indices.
*/
class CFIndex extends NativeLong {
private static final long serialVersionUID = 1L;
View on GitHub (pinned to d036ad9781)