java-native-access/jna · error · IllegalArgumentException

DACL is invalid

Error message

DACL is invalid

What it means

When setDACL is requested and a DACL is present, the library validates it with Advapi32.IsValidAcl. If the ACL structure fails Windows validation (bad AclRevision, size mismatch, corrupted ACEs), it throws IllegalArgumentException ('DACL is invalid').

Source

Thrown at contrib/platform/src/com/sun/jna/platform/win32/Advapi32Util.java:2893

                throw new IllegalArgumentException("SECURITY_DESCRIPTOR_RELATIVE does not contain owner");
            if (!Advapi32.INSTANCE.IsValidSid(psidOwner))
                throw new IllegalArgumentException("Owner PSID is invalid");
            infoType |= OWNER_SECURITY_INFORMATION;
        }

        if (setGroup) {
            if (psidGroup == null)
                throw new IllegalArgumentException("SECURITY_DESCRIPTOR_RELATIVE does not contain group");
            if (!Advapi32.INSTANCE.IsValidSid(psidGroup))
                throw new IllegalArgumentException("Group PSID is invalid");
            infoType |= GROUP_SECURITY_INFORMATION;
        }

        if (setDACL) {
            if (dacl == null)
                throw new IllegalArgumentException("SECURITY_DESCRIPTOR_RELATIVE does not contain DACL");
            if (!Advapi32.INSTANCE.IsValidAcl(dacl.getPointer()))
                throw new IllegalArgumentException("DACL is invalid");
            infoType |= DACL_SECURITY_INFORMATION;
        }

        if (setSACL) {
            if (sacl == null)
                throw new IllegalArgumentException("SECURITY_DESCRIPTOR_RELATIVE does not contain SACL");
            if (!Advapi32.INSTANCE.IsValidAcl(sacl.getPointer()))
                throw new IllegalArgumentException("SACL is invalid");
            infoType |= SACL_SECURITY_INFORMATION;
        }

        /*
         * Control bits SE_DACL_PROTECTED/SE_SACL_PROTECTED indicate the *ACL is protected. The *ACL_SECURITY_INFORMATION flags
         * are meta flags for SetNamedSecurityInfo and are not stored in the SD.  If either *ACLProtectedStatus is set,
         * get the current status from the securityDescriptor and apply as such, otherwise the ACL remains at its default.
        */
        if (setDACLProtectedStatus) {
            if ((securityDescriptor.Control & SE_DACL_PROTECTED) != 0) {

View on GitHub (pinned to d036ad9781)

Solutions

  1. Pre-check with Advapi32.INSTANCE.IsValidAcl(dacl.getPointer()) and rebuild the ACL if false.
  2. Rebuild the DACL with Advapi32Util.createAccessControlList or similar helper rather than hand-writing bytes.
  3. Re-extract the ACL from the source descriptor using the correct offsets (getSecurityDescriptorDacl).
  4. Skip the DACL component (setDACL=false) if invalid, then set it separately from a freshly built ACL.

Example fix

// before
Advapi32Util.setSecurityDescriptorComponents(sd, true, true, true, true, false, false);
// after
if (sd.getDiscretionaryACL() != null && Advapi32.INSTANCE.IsValidAcl(sd.getDiscretionaryACL().getPointer())) {
    Advapi32Util.setSecurityDescriptorComponents(sd, true, true, true, true, false, false);
}
Defensive patterns

Strategy: validation

Validate before calling

ACL dacl = securityDescriptor.getDiscretionaryACL();
if (dacl == null || !Advapi32.INSTANCE.IsValidAcl(dacl.getPointer())) {
    throw new IllegalStateException("DACL missing or invalid");
}

Type guard

boolean isValidDACL(SECURITY_DESCRIPTOR_RELATIVE sd) {
    ACL a = sd.getDiscretionaryACL();
    return a != null && Advapi32.INSTANCE.IsValidAcl(a.getPointer());
}

Try / catch

try {
    Advapi32Util.setSecurityDescriptorComponents(sd, false, false, true, false, false, false);
} catch (IllegalArgumentException e) {
    log.error("DACL rejected: " + e.getMessage());
}

Prevention

When it happens

Trigger: setDACL=true where the ACL bytes are corrupted or inconsistent: declared AclSize not matching buffer, malformed ACEs, ACL built by hand with wrong header fields.

Common situations: Manually constructed ACL structures with incorrect ACE sizes; copying ACL memory between descriptors without fixing offsets; truncated descriptor buffers causing partial ACL reads.

Understand the failure class

Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.

Related errors


AI-assisted analysis of java-native-access/jna@d036ad9781 (2026-09-12). Data as JSON: /api/errors/fbb9ef441469bdc1. Report an issue: GitHub.