Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion Maple2.File.Generator/Resource/FeatureLocaleFilter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,9 @@ private static T Resolve<T>(this IEnumerable<T> enumerable) where T : IFeatureLo
}

int version = Features[entry.Feature];
if (version > maxVersion) {
if (version > maxVersion ||
// This is how the client resolves same version matches. Dumb as bricks.
(version == maxVersion && string.Compare(entry.Feature, result.Feature, StringComparison.Ordinal) > 0)) {
Comment on lines +68 to +70
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Latent NullReferenceException when the first feature entry has version −1

result starts as default(T)null for any reference-type T. The tie-breaker arm version == maxVersion fires the moment a feature entry's version matches the initial sentinel value of −1 (i.e. Features[entry.Feature] == -1). If that happens before any prior entry has set result, the expression result.Feature dereferences a null object and throws.

Note that string.Compare itself is null-safe for its string arguments (one or both comparands can be null — by definition, any string compares greater than a null reference), so the problem is specifically the member access on result, not the comparison call.

The correct guard also covers the semantics correctly: a null result should always be replaced by any feature entry at the same version (just as any feature beats no-feature).

🛡️ Proposed fix
-            if (version > maxVersion ||
-                // This is how the client resolves same version matches. Dumb as bricks.
-                (version == maxVersion && string.Compare(entry.Feature, result.Feature, StringComparison.Ordinal) > 0)) {
+            if (version > maxVersion ||
+                // This is how the client resolves same version matches. Dumb as bricks.
+                (version == maxVersion && (result == null || string.Compare(entry.Feature, result.Feature, StringComparison.Ordinal) > 0))) {
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
if (version > maxVersion ||
// This is how the client resolves same version matches. Dumb as bricks.
(version == maxVersion && string.Compare(entry.Feature, result.Feature, StringComparison.Ordinal) > 0)) {
if (version > maxVersion ||
// This is how the client resolves same version matches. Dumb as bricks.
(version == maxVersion && (result == null || string.Compare(entry.Feature, result.Feature, StringComparison.Ordinal) > 0))) {
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@Maple2.File.Generator/Resource/FeatureLocaleFilter.cs` around lines 68 - 70,
The tie-breaker condition in FeatureLocaleFilter that reads (version ==
maxVersion && string.Compare(entry.Feature, result.Feature,
StringComparison.Ordinal) > 0) can dereference result (default(T) / null) when
the first seen entry has version == maxVersion (e.g. Features[entry.Feature] ==
-1); modify the condition to first check result == null before accessing
result.Feature so that any entry at the same version always replaces a null
result. In practice update the if in the method using variables version,
maxVersion, entry and result to: if (version > maxVersion || (version ==
maxVersion && (result == null || string.Compare(entry.Feature, result.Feature,
StringComparison.Ordinal) > 0))) so result is not dereferenced.

result = entry;
maxVersion = version;
}
Expand Down
2 changes: 1 addition & 1 deletion Maple2.File.Parser/Maple2.File.Parser.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
<PackageTags>MapleStory2, File, Parser, m2d, xml</PackageTags>
<!-- Use following lines to write the generated files to disk. -->
<EmitCompilerGeneratedFiles Condition=" '$(Configuration)' == 'Debug' ">true</EmitCompilerGeneratedFiles>
<PackageVersion>2.4.6</PackageVersion>
<PackageVersion>2.4.7</PackageVersion>
<TargetFramework>net8.0</TargetFramework>
<PackageReadmeFile>README.md</PackageReadmeFile>
<ImplicitUsings>enable</ImplicitUsings>
Expand Down
Loading