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

  1. Verify the pointer is a valid CFString (isTypeID(STRING_TYPE_ID)) before calling stringValue(); corrupt pointers are the usual cause.
  2. Wrap stringValue() in try-catch for StringIndexOutOfBoundsException and fall back to an alternate conversion or empty string.
  3. Re-acquire the string from the source API instead of reusing a possibly-released CFString reference.
  4. 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

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


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)