{"record":{"id":"dfdb692605ffba02","repo":"NationalSecurityAgency/ghidra","slug":"mask-and-a-must-have-equal-capacities","errorCode":null,"errorMessage":"mask and a must have equal capacities","messagePattern":"mask and a must have equal capacities","errorType":"validation","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"Ghidra/Debug/ProposedUtils/src/main/java/ghidra/util/ByteBufferUtils.java","lineNumber":74,"sourceCode":"\n\t/**\n\t * Checks for equality, with a mask applied\n\t * \n\t * <p>\n\t * This considers the entire contents of both buffers without regard for position or limit. Both\n\t * buffers must have equal capacities to be considered equal. The mask, if given, must have\n\t * capacity equal to that of the first buffer {@code a} or an exception is thrown.\n\t * \n\t * @param mask a buffer containing the mask, or null to match all bytes exactly\n\t * @param a the first buffer\n\t * @param b the second buffer\n\t * @return true if matches, false otherwise\n\t * @throws IllegalArgumentException if {@code mask} and {@code a} have unequal capacities\n\t */\n\tpublic static boolean maskedEquals(ByteBuffer mask, ByteBuffer a, ByteBuffer b) {\n\t\tint len = a.capacity();\n\t\tif (mask != null && mask.capacity() != len) {\n\t\t\tthrow new IllegalArgumentException(\"mask and a must have equal capacities\");\n\t\t}\n\t\tif (len != a.capacity()) {\n\t\t\treturn false;\n\t\t}\n\t\tif (mask != null) {\n\t\t\tfor (int i = 0; i < len; i++) {\n\t\t\t\tif ((a.get(i) & mask.get(i)) != (b.get(i) & mask.get(i))) {\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn true;\n\t\t}\n\t\tfor (int i = 0; i < len; i++) {\n\t\t\tif (a.get(i) != b.get(i)) {\n\t\t\t\treturn false;\n\t\t\t}\n\t\t}\n\t\treturn true;","sourceCodeStart":56,"sourceCodeEnd":92,"githubUrl":"https://github.com/NationalSecurityAgency/ghidra/blob/d5f144c24d6bc53c9cbf4448c6d11143e7696206/Ghidra/Debug/ProposedUtils/src/main/java/ghidra/util/ByteBufferUtils.java#L56-L92","documentation":"Thrown (unchecked IllegalArgumentException) by ByteBufferUtils.maskedEquals() when a non-null mask buffer's capacity differs from buffer a's capacity. The mask is applied byte-for-byte against both a and b, so it must be the same length as a; a mismatched mask would read out of bounds or mis-compare.","triggerScenarios":"Calling maskedEquals(mask, a, b) where mask.capacity() != a.capacity() — e.g. reusing a mask buffer sized for a different record, building a mask from a wrong-length pattern, or passing a partial mask.","commonSituations":"Pattern-matching binary signatures where the mask (wildcard bytes) was generated for a different-length signature; copying a mask buffer between unrelated comparisons; a mask built from a hex pattern with the wrong byte count.","solutions":["Size the mask to exactly a.capacity() before calling (ByteBuffer.allocate(a.capacity()) and fill mask bytes).","Pass null as the mask when you want exact (unmasked) equality.","Validate mask == null || mask.capacity() == a.capacity() before the call and fix the mask source if it mismatches."],"exampleFix":"// before\nboolean eq = ByteBufferUtils.maskedEquals(mask, a, b); // throws if mask shorter than a\n\n// after: right-size the mask to a\nByteBuffer sizedMask = mask != null && mask.capacity() != a.capacity()\n    ? resizeMaskTo(mask, a.capacity()) : mask;\nboolean eq = ByteBufferUtils.maskedEquals(sizedMask, a, b);","handlingStrategy":"validation","validationCode":"// Validate mask length against buffer a before comparing\nif (mask != null && mask.capacity() != a.capacity()) {\n    // resize/rebuild mask to a.capacity(), or pass null for exact match\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Size the mask buffer to exactly a.capacity().","Pass null mask for exact (unmasked) equality.","Regenerate masks whenever the signature length changes."],"tags":["bytebuffer","mask","compare","capacity","illegal-argument","unchecked-exception"],"backgroundTag":null,"analyzedSha":"d5f144c24d6bc53c9cbf4448c6d11143e7696206","analyzedAt":"2026-08-14T01:00:57.564Z","schemaVersion":2},"datasetVersion":"2026-08-14T05:17:29.042Z"}