Skip to content

fix: add null guard for writeEnum and enumCapacity in JSONB.IO (#7806) - #7831

Open
waterWang wants to merge 1 commit into
alibaba:mainfrom
waterWang:fix-7806-writeenum-null-guard
Open

fix: add null guard for writeEnum and enumCapacity in JSONB.IO (#7806)#7831
waterWang wants to merge 1 commit into
alibaba:mainfrom
waterWang:fix-7806-writeenum-null-guard

Conversation

@waterWang

Copy link
Copy Markdown

Summary

Fixes #7806: NPE when serializing an object with a null enum field via JSONB.toBytes with WriteNulls (and WriteClassName).

Root cause

When JSONB.toBytes(obj, WriteNulls, ...) runs on a class with an enum field whose value is null, the ASM-generated ObjectWriter (class OWG_*) serializes the field through JSONB.IO.writeEnum(byte[], int, Enum, long) directly. That method had no null guard — with e == null it accessed e.ordinal() and threw NullPointerException.

java.lang.NullPointerException
  at com.alibaba.fastjson2.JSONB$IO.writeEnum(JSONB.java:2196)
  at com.alibaba.fastjson2.writer.OWG_1_5_ResultValue.writeJSONB
  at com.alibaba.fastjson2.JSONB.toBytes(JSONB.java:1836)

The companion JSONB.IO.enumCapacity (used for buffer pre-allocation) had the same missing guard.

FieldWriterEnum.writeEnumValueJSONB already handled null correctly (writes BC_NULL), but the ASM fast path bypassed it when symbolTable is null.

Fix

Add early null checks to both methods in JSONB.IO:

  • writeEnum: write BC_NULL (1 byte) when e is null, return off + 1
  • enumCapacity: return 1 (the BC_NULL size) when e is null

This matches the existing null handling in FieldWriterEnum.writeEnumValueJSONB and JSONWriter.writeEnum.

Verification

Reproduced the exact stack trace on main, then confirmed the fix:

  • null enum + WriteNulls + WriteClassName → serializes color:null (previously NPE)
  • non-null enum unchanged
  • JSON text path unaffected

One file changed (+7). No functional change for non-null enum values.

…ba#7806)

When JSONB.toBytes is called with WriteNulls enabled on an object
whose enum field is null, the ASM-generated ObjectWriter (OWG)
directly calls JSONB.IO.writeEnum(byte[], int, Enum, long), which
did not handle null e — accessing e.ordinal() threw NullPointerException.

The same issue affects JSONB.IO.enumCapacity which is called during
buffer pre-allocation.

Fix by adding early null checks in both methods:
  - writeEnum: write BC_NULL (1 byte) when e is null
  - enumCapacity: return 1 (BC_NULL size) when e is null

FieldWriterEnum.writeEnumValueJSONB already had the same null guard
(writes BC_NULL), but the ASM-generated fast path bypassed it when
symbolTable is null.

Closes alibaba#7806
@CLAassistant

Copy link
Copy Markdown

CLA assistant check
Thank you for your submission! We really appreciate it. Like many open source projects, we ask that you sign our Contributor License Agreement before we can accept your contribution.
You have signed the CLA already but the status is still pending? Let us recheck it.

@wenshao wenshao left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reviewed. Suggestions are inline.

— gpt-5.6-sol@954e5164 via Qwen Code /review (v0.22.0)

Comment on lines +2171 to +2173
if (e == null) {
return 1;
}

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[Suggestion] Add a regression test for the ASM null-enum JSONB path

This fixes the production path, but no test pins the generated OWG_* direct writer that triggered issue 7806. A later refactor could remove or bypass either guard and JSONB.toBytes(bean, WriteNulls, WriteClassName) would again throw while the current suite remains green.

An isolated probe confirmed the generated writer was OWG_1_1_Bean; removing the writeEnum guard produced:

java.lang.NullPointerException: Cannot invoke "java.lang.Enum.ordinal()" because "e" is null
 at com.alibaba.fastjson2.JSONB$IO.writeEnum(JSONB.java:2199)
 at com.alibaba.fastjson2.writer.OWG_1_1_Bean.writeJSONB(Unknown Source)

Please add an Issue7806 regression test with a null enum field through the ASM writer, asserting WriteNulls + WriteClassName preserves null and a non-null value remains unchanged. Add a WriteEnumsUsingName or WriteEnumUsingToString variant to independently pin enumCapacity's guard. The test must fail when the writeEnum guard is removed, and the enum-name/toString variant must fail when the enumCapacity guard is removed.

— gpt-5.6-sol@954e5164 via Qwen Code /review (v0.22.0)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[BUG]从2.0.61版本开始,使用JSONB类的toBytes方法报错

3 participants