Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Replace malloc's with Godot's memalloc macro #46900

Merged
merged 1 commit into from
Mar 13, 2021

Conversation

rsubtil
Copy link
Contributor

@rsubtil rsubtil commented Mar 11, 2021

Replaces some "raw" calls to malloc and handle error scenarios.

Fixes #46807

@rsubtil rsubtil requested review from a team as code owners March 11, 2021 16:04
@akien-mga akien-mga added this to the 4.0 milestone Mar 11, 2021
@akien-mga akien-mga added the cherrypick:3.x Considered for cherry-picking into a future 3.x release label Mar 11, 2021
@akien-mga
Copy link
Member

akien-mga commented Mar 11, 2021

Shouldn't you use memfree() to free memory allocated with memalloc()?

Edit: @reduz confirmed that the matching free() calls should be changed to memfree() too.

@@ -636,7 +635,8 @@ GD_PINVOKE_EXPORT int32_t _monodroid_get_dns_servers(void **r_dns_servers_array)

if (dns_servers_count > 0) {
size_t ret_size = sizeof(char *) * (size_t)dns_servers_count;
*r_dns_servers_array = malloc(ret_size); // freed by the BCL
*r_dns_servers_array = memalloc(ret_size); // freed by the BCL
ERR_FAIL_NULL_MSG(r_dns_servers_array, "Out of memory.");
Copy link
Contributor

@neikeq neikeq Mar 11, 2021

Choose a reason for hiding this comment

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

Like the comment says, this is freed by the Mono BCL which doesn't use Godot's memfree (Memory::free_static). Isn't that going to cause trouble?
Honestly, I would prefer this file wasn't touched. Mono's allocations don't use Godot's allocation macros any way.

Copy link
Member

Choose a reason for hiding this comment

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

See #46807 - if malloc fails (e.g. OOM), this can lead to a null pointer dereference.

But yes in this file we can likely add ERR_FAIL_NULL_MSG on the result of malloc() without changing it to Godot's static alloc.

@rsubtil rsubtil force-pushed the bugfix-malloc_calls branch from 1f1fcf7 to 05f3a47 Compare March 12, 2021 11:02
@rsubtil
Copy link
Contributor Author

rsubtil commented Mar 12, 2021

Quick summary of the changes I've made:

  • modules/bullet/space_bullet.cpp: reverted to malloc as the pointer is used elsewhere, in a way I honestly don't understand how 😅
  • modules/upnp/upnp.cpp: reverted to malloc, the pointer is freed using a custom method
  • modules/xatlas_unwrap/register_types.cpp: changed free's on scene/resources/mesh.cpp

Other than these, I've changed the corresponding free's to Godot's macro. I was also wrongly testing some allocations (testing r_vertices when I should be testing *r_vertices, for example), so I've fixed those as well.

(I am depending on the CI to know if this compiles to the many platforms this affects, so I might need to do quite some force-pushes)

scene/resources/mesh.cpp Outdated Show resolved Hide resolved
@rsubtil rsubtil force-pushed the bugfix-malloc_calls branch from 05f3a47 to 91dc2f2 Compare March 12, 2021 11:13
Comment on lines 163 to 168
*r_vertices = (int *)memalloc(sizeof(int) * output.vertexCount);
ERR_FAIL_NULL_V_MSG(*r_vertices, false, "Out of memory.");
*r_uvs = (float *)memalloc(sizeof(float) * output.vertexCount * 2);
ERR_FAIL_NULL_V_MSG(*r_uvs, false, "Out of memory.");
*r_indices = (int *)memalloc(sizeof(int) * output.indexCount);
ERR_FAIL_NULL_V_MSG(*r_indices, false, "Out of memory.");
Copy link
Member

@akien-mga akien-mga Mar 12, 2021

Choose a reason for hiding this comment

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

These are members of xatlas::Mesh which is in thirdparty code and doesn't use memfree(), so I'm not sure they should be changed to memalloc(). CC @reduz

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Reverted to malloc, and reverted to normal free's in scene/resources/mesh.cpp

Copy link
Member

@akien-mga akien-mga Mar 13, 2021

Choose a reason for hiding this comment

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

I think there was confusion here, xatlas::Mesh is not related to scene/resources/mesh.cpp. xatlas is a thirdparty library in thirdparty/xatlas/, and it has its own Mesh struct.

For Godot's Mesh, whether or not those values should be memfreed depends on how they're allocated initially. I did see some memalloc related to that code but I'm not so confident to say if the change should be kept.

*r_value = (char *)malloc(len + 1);
if (!*r_value)
return -1;
*r_value = (char *)memalloc(len + 1);
Copy link
Member

Choose a reason for hiding this comment

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

This is freed at line 629 and should be changed to memfree() - or kept as malloc() here if @neikeq thinks it's better.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Nice catch 🙂. I couldn't find any call to this method, maybe VSCode is skipping files that are ignored due to #if guards, I'll have to see if I can fix this.

I agree to use malloc here again; honestly, I'm scared of the scope this PR has, so maybe we should just stick with malloc where there are worries it might break something. The objective is to prevent null de-references from happening anyways.

Copy link
Contributor

Choose a reason for hiding this comment

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

I prefer to keep it as it was as I'm not 100% sure it's always freed with the monodroid_free we implement above. I prefer not to risk.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Fixed

@rsubtil rsubtil force-pushed the bugfix-malloc_calls branch from 91dc2f2 to 838e7d0 Compare March 13, 2021 11:51
Copy link
Member

@akien-mga akien-mga left a comment

Choose a reason for hiding this comment

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

Looks great! The current subset of changes seems safe to me :)

@akien-mga akien-mga merged commit 7015027 into godotengine:master Mar 13, 2021
@akien-mga
Copy link
Member

Thanks!

@akien-mga
Copy link
Member

Cherry-picked for 3.2.4.

@akien-mga akien-mga removed the cherrypick:3.x Considered for cherry-picking into a future 3.x release label Mar 13, 2021
akien-mga added a commit that referenced this pull request Mar 18, 2021
akien-mga added a commit that referenced this pull request Mar 18, 2021
(cherry picked from commit 2274d4e)
lekoder pushed a commit to KoderaSoftwareUnlimited/godot that referenced this pull request Apr 24, 2021
@rsubtil rsubtil deleted the bugfix-malloc_calls branch June 1, 2021 09:10
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Unchecked malloc return NULL vulnerability
4 participants