Repository navigation
Reject attributes the SDKs would clamp - #7
Conversation
Co-authored-by: Cursor <cursoragent@cursor.com>
There was a problem hiding this comment.
Stale comment
Deep code review — PR #7 (Reject attributes the SDKs would clamp)
Policy-only PR (same shape as the other wrapper-policy PRs):
AttributePolicy/UserIdentifierPolicyplus isolated net8 tests. I compared it to the existing Unity bridges and to the React Native Phase 5 rules this is clearly porting (validateAttributeValue,isWithinBundleNumberLimit,normalizeIdentifier).Findings
P2 Medium —
sbyte/ushort/uint/ulong/decimalare rejected as non-numbers
- Location:
Runtime/WrapperPolicy/AttributePolicy.cs:32-36- Problem: The switch only matches
byte/short/int/long(plusfloat/double). C# pattern matching does not treat a boxeduintasint. Those values hitdefaultand return"must be string, bool, or number"even when they are finite and inside the signed 64-bit range.- Impact: The method's stated job is the RN/Android bundle domain (
string | bool | finite number with |x| < 2^63). Once this is wired toBugsee.SetAttribute, Unity callers passinguintscores,ulongIDs, orsbytewill be refused. iOS already serializes all of those as JSON numbers inIOSBridge.ToJsonValue.- Scenario:
AttributePolicy.Evaluate("wave", 3u)→Accepted = false. Same for(sbyte)(-1),(ushort)1,1UL,1m.- Fix: Accept every primitive numeric
TypeCode. Keep the existing 2^63 exclusive bound forfloat/double. Forulong/decimal, apply the same bound (ulong > long.MaxValue,|decimal| >= 2^63); a barecase ulong _:would acceptulong.MaxValue, which Android's JSON writer would clamp.P3 Low — NaN / ±Infinity reuse the type-error message
- Location:
Runtime/WrapperPolicy/AttributePolicy.cs:48-49and55-56- Problem: Non-finite numbers are rejected with
"must be string, bool, or number", the same text asDateTime. RN splits this: non-finite vs|x| >= 2^63vs wrong type.- Impact: A computed
double.NaNis a number; the message tells the caller the type is wrong.- Scenario:
Evaluate("n", double.NaN)andEvaluate("n", DateTime.UtcNow)produce the same error class of text. The test asserts onlyAccepted.- Fix: Use a finite/bound message for NaN/∞ (and keep not echoing the value).
P3 Low — attribute names are not validated
- Location:
Runtime/WrapperPolicy/AttributePolicy.cs:22- Problem:
keyis only interpolated into errors.Evaluate("", "x")andEvaluate(null, true)returnAccepted = true. RNvalidateAttributeNamerejects empty/non-string names;IosReport.SetAttributealready no-ops on empty names.- Impact: A later facade that only consults
Evaluatewill still send empty/null keys to JNI /setAttribute:withValue:.- Scenario:
Bugsee.SetAttribute("", "ok")after wiring.- Fix: Reject null/empty keys in
Evaluate(or add a sibling name check and call both from the facade).No P0/P1. I did not run
dotnet test—dotnetis not installed in this environment.Overall
- Overall risk: Medium
- Merge recommendation: Request changes — fix the numeric
TypeCodegap before this becomes the SetAttribute gate.- Most important to fix: Treat
sbyte/ushort/uint/ulong/decimalas numbers, with the 2^63 exclusive bound on the unsigned/decimal paths.- What looks good:
|x| >= 2^63matches RN/isWithinBundleNumberLimit(AndroidlongValue()clamp). 1024 is UTF-16 units, matching Android. Rejection text names the key and the decimal bound9223372036854775808without echoing the value (avoidsdouble.ToStringrounding). Empty user identifier → null on set and get matches both native SDKs and RNnormalizeIdentifier.Sent by Cursor Automation: Bugsee code review
Address automated review: TypeCode coverage for unsigned integers and decimal, non-finite floats use the magnitude error text, and empty attribute names reject. Co-authored-by: Cursor <cursoragent@cursor.com>
There was a problem hiding this comment.
Deep code review — PR #7 (47612b7)
Re-review after Accept all primitive numeric attribute types and validate names. Compared again to RN Phase 5 (validateAttributeValue / isWithinBundleNumberLimit / normalizeIdentifier), IOSBridge.ToJsonValue, and AndroidJavaConverters.Box. Policy is still unwired from Bugsee.SetAttribute (same shape as the other wrapper-policy PRs).
Prior findings
- P2 numeric TypeCodes — fully_addressed.
Type.GetTypeCodecoverssbyte/ushort/uint/ulong/decimal.ulonganddecimaluse the exclusive 2^63 bound (ulong.MaxValueand±9223372036854775808mreject;(ulong)long.MaxValueand(decimal)long.MaxValueaccept). CLR unbox of aulong-backed enum toulongsucceeds, so that cast does not throw. - P3 NaN/±Infinity message — fully_addressed. Non-finite floats take
MagnitudeError(same combined finite/bound text RN uses). Test asserts the decimal bound, not the type-error string. - P3 empty names — fully_addressed.
string.IsNullOrEmpty(key)rejects""andnull.
Findings
No remaining P0–P3. I ran DOTNET_ROLL_FORWARD=LatestMajor dotnet test Tests~/WrapperPolicy/Bugsee.WrapperPolicy.Tests.csproj --filter AttributePolicyTests: 6/6 passed. Extra probes (unsigned bounds, ±2^63 decimal, long.MinValue as long vs double, UTF-16 emoji length, char, enums) matched the intended domain.
Residual only (not blocking): no Unity .meta for Runtime/WrapperPolicy/ on this branch (sibling policy PRs commit them). These types are static and unreferenced by GUID, so import churn is the only effect. When wiring the facade, AndroidJavaConverters.Box still stringifies uint/ulong/sbyte/decimal — a pre-existing bridge gap, not this policy.
Overall
- Overall risk: Low
- Merge recommendation: Approve
- Most important to fix: Nothing in this PR. Next step is calling
Evaluate/ForSet/ForGetfrom the facade (and tightening AndroidBoxso accepted numeric TypeCodes stay numbers). - What looks good: Intersection domain matches RN/Android (string / bool / finite number with
|x| < 2^63, 1024 UTF-16 units). Rejection text names the key and the exact decimal bound9223372036854775808without echoing the value. Empty user identifier → null on set and get matches both native SDKs andnormalizeIdentifier.
Sent by Cursor Automation: Bugsee code review


Summary
AttributePolicyaccepts only string, bool, and finite numbers inside the signed 64-bit range, and caps strings at 1024 UTF-16 units.Test plan
DOTNET_ROLL_FORWARD=LatestMajor dotnet test Tests~/WrapperPolicy/Bugsee.WrapperPolicy.Tests.csproj --filter AttributePolicyTestsMade with Cursor