Commit 4a6399a
Fix memory leaks from mono_type_full_name in marshal-shared.c error paths (dotnet#125616)
`mono_type_full_name()` returns a heap-allocated string, but several
call sites in `marshal-shared.c` passed the result directly into
`g_strdup_printf` without freeing it — leaking on every hit. These paths
can fire repeatedly during AOT compilation against assemblies with many
invalid marshal configurations.
# Description
Store each `mono_type_full_name()` result in a local, use it, then
`g_free` it:
```c
// Before
char *msg = g_strdup_printf("Type %s ...", mono_type_full_name(m_class_get_byval_arg(klass)));
// After
char *type_name = mono_type_full_name(m_class_get_byval_arg(klass));
char *msg = g_strdup_printf("Type %s ...", type_name);
g_free(type_name);
```
Fixed sites:
- **Auto-layout check** — `g_strdup_printf` with single
`mono_type_full_name`; result stored, used, and freed
- **Explicit-layout `g_error` path** — left as-is (inline
`mono_type_full_name` call); `g_error` is fatal and never returns, and
in `DISABLE_ASSERT_MESSAGES` builds its variadic args are discarded
entirely — introducing a local variable causes an unused-variable build
error in WASM/WASI configurations
- **Generic type marshal check** — `g_strdup_printf` with single
`mono_type_full_name`; result stored, used, and freed
- **Struct field type check** — `g_strdup_printf` with two
`mono_type_full_name` calls; both results stored, used, and freed
# Customer Impact
Cumulative memory growth during AOT compilation of assemblies containing
types with invalid marshal configurations (auto-layout structs,
non-blittable generic fields, reference-typed struct fields).
# Regression
No — pre-existing leak, not a regression.
# Testing
Validated by code inspection and CI. These are error paths with no
dedicated test infrastructure in the repo; the fix is mechanical and
low-risk.
# Risk
Very low. Changes are confined to error paths that emit a marshal
exception. No logic changes — only introduction of local variables and
paired `g_free` calls before strings go out of scope. The `g_error` path
is intentionally left unchanged to avoid a `-Werror,-Wunused-variable`
build failure in WASM/WASI configurations where `g_error` discards its
variadic arguments.
# Package authoring no longer needed in .NET 9
IMPORTANT: Starting with .NET 9, you no longer need to edit a NuGet
package's csproj to enable building and bump the version.
Keep in mind that we still need package authoring in .NET 8 and older
versions.
<!-- START COPILOT ORIGINAL PROMPT -->
<details>
<summary>Original prompt</summary>
>
> ----
>
> *This section details on the original issue you should resolve*
>
> <issue_title>Memory leaks from mono_type_full_name in marshal-shared.c
error paths</issue_title>
> <issue_description>## Description
>
> `mono_type_full_name()` returns an allocated string, but several call
sites in `src/mono/mono/metadata/marshal-shared.c` pass it directly into
`g_strdup_printf` or `g_error` without freeing the intermediate
allocation:
>
> - **Line 778**: `g_strdup_printf("Type %s ...",
mono_type_full_name(...))`
> - **Line 816**: `g_error("Type %s ...", mono_type_full_name(...))`
> - **Line 866**: `g_strdup_printf("Generic type %s ...",
mono_type_full_name(...))`
> - **Lines 912-913**: `g_strdup_printf("Type %s with field type %s
...", mono_type_full_name(...), mono_type_full_name(...))`
>
> Each leaks the string returned by `mono_type_full_name()`. While these
are error paths, they can fire repeatedly during AOT compilation (e.g.,
when processing assemblies with many invalid marshal configurations),
causing cumulative memory growth.
>
> ## Fix
>
> Store the result in a temporary, use it in the format string, then
`g_free` it:
>
> ```c
> char *type_name = mono_type_full_name(m_class_get_byval_arg(klass));
> char *msg = g_strdup_printf("Type %s ...", type_name);
> g_free(type_name);
> mono_marshal_shared_mb_emit_exception_marshal_directive(mb, msg);
> ```
>
> This pattern should be applied to all call sites in the
file.</issue_description>
>
> ## Comments on the Issue (you are @copilot in this section)
>
> <comments>
> </comments>
>
</details>
<!-- START COPILOT CODING AGENT SUFFIX -->
- Fixes dotnet#125576
<!-- START COPILOT CODING AGENT TIPS -->
---
🔒 GitHub Advanced Security automatically protects Copilot coding agent
pull requests. You can protect all pull requests by enabling Advanced
Security for your repositories. [Learn more about Advanced
Security.](https://gh.io/cca-advanced-security)
---------
Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: lewing <24063+lewing@users.noreply.github.com>
Co-authored-by: Larry Ewing <lewing@microsoft.com>1 parent baa4920 commit 4a6399a
1 file changed
Lines changed: 12 additions & 4 deletions
File tree
- src/mono/mono/metadata
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
774 | 774 | | |
775 | 775 | | |
776 | 776 | | |
| 777 | + | |
777 | 778 | | |
778 | | - | |
| 779 | + | |
| 780 | + | |
779 | 781 | | |
780 | 782 | | |
781 | 783 | | |
| |||
862 | 864 | | |
863 | 865 | | |
864 | 866 | | |
| 867 | + | |
865 | 868 | | |
866 | | - | |
| 869 | + | |
| 870 | + | |
867 | 871 | | |
868 | 872 | | |
869 | 873 | | |
| |||
908 | 912 | | |
909 | 913 | | |
910 | 914 | | |
| 915 | + | |
| 916 | + | |
911 | 917 | | |
912 | | - | |
913 | | - | |
| 918 | + | |
| 919 | + | |
| 920 | + | |
| 921 | + | |
914 | 922 | | |
915 | 923 | | |
916 | 924 | | |
| |||
0 commit comments