CMake: add WITH_STRSIZE_DEBUG option, RNA support #107602

Closed
Campbell Barton wants to merge 1 commits from ideasman42/blender:pr-debug-strsize into main

When changing the target branch, be careful to rebase the branch in your fork to match. See documentation.

Support string size debug so it can be used for regular development.

It works be writing values into strings, ensuring the buffer size
given is actually available. Developers can use this with memory
checking tools such as ASAN/valgrind to force an error when
the value used for the size of a buffer is larger than the buffer.

Resolve remaining issue with RNA using BLI_strncpy* in generated
callback functions where the size argument didn't represent the
size of the destination buffer.

This is automatically enabled along with ASAN for the
blender_developer.cmake configuration.


This PR proposes to make WITH_STRSIZE_DEBUG a build-time option that developers can keen enabled, similar to ASAN.

There have been potential buffer overflows in Blender's code for years, these mostly went by unnoticed as users just didn't trigger with overly long strings, although a some were fairly easy to trigger.

The following issues were detecting using this method:


Possible Changes

  • CMake could be longer e.g. WITH_STRING_SIZE_DEBUG
  • The define checked in the code should match the CMake option (could be done separately). Left this out to avoid noisy changes.
Support string size debug so it can be used for regular development. It works be writing values into strings, ensuring the buffer size given is actually available. Developers can use this with memory checking tools such as ASAN/valgrind to force an error when the value used for the size of a buffer is larger than the buffer. Resolve remaining issue with RNA using BLI_strncpy* in generated callback functions where the size argument didn't represent the size of the destination buffer. This is automatically enabled along with ASAN for the `blender_developer.cmake` configuration. --- This PR proposes to make `WITH_STRSIZE_DEBUG` a build-time option that developers can keen enabled, similar to ASAN. There have been potential buffer overflows in Blender's code for years, these mostly went by unnoticed as users just didn't trigger with overly long strings, although a some were fairly easy to trigger. The following issues were detecting using this method: - 91325378cbf59ffca5db0965d01fba2e5cb669c3 - ff0cf45bc2fd6cc76971de740ec17f2e7e4b90bd - ba978e1b6823c33f0cae051db2d982b7b3ea649f - e462e20e2158556bae5d0e67bc01d63410f1bca8 ---- ### Possible Changes - CMake could be longer e.g. `WITH_STRING_SIZE_DEBUG` - The define checked in the code should match the CMake option (could be done separately). _Left this out to avoid noisy changes._
Campbell Barton added the
Interest
Core
label 2023-05-04 06:39:59 +02:00
Campbell Barton requested review from Bastien Montagne 2023-05-04 06:40:10 +02:00
Campbell Barton requested review from Brecht Van Lommel 2023-05-04 06:40:23 +02:00

While I see the point of the patch, I am not so convinced by the solution proposed here.

Having to add such clutter to all RNA string accessors does not really sounds good to me, to say the least. Not to mention that other places in code would most likely need such checks too? Which implies also the need to manually identify such places, etc.

Is there a reason (when the debug option is on) not to e.g. systematically write (or even read actually) the whole allowed size in destination buffer in BLI_string functions? This should trigger ASAN & co just as well, and ensures all code calling BLI_string copy etc. functions is checked for proper buffer maxsizes, without having to manually modify it?

Also, I do not understand the need for the _nodebug versions of the BLI_string functions, can you explain more in details?

Finally, agree with your notes regarding naming. In fact, could even use a more generic name (WITH_BUFFER_SIZE_DEBUG ?), and in the future we could have our own memcpy wrapper that would perform the same type of checks too?

While I see the point of the patch, I am not so convinced by the solution proposed here. Having to add such clutter to all RNA string accessors does not really sounds good to me, to say the least. Not to mention that other places in code would most likely need such checks too? Which implies also the need to manually identify such places, etc. Is there a reason (when the debug option is on) not to e.g. systematically write (or even read actually) the whole allowed size in destination buffer in BLI_string functions? This should trigger ASAN & co just as well, and ensures all code calling BLI_string copy etc. functions is checked for proper buffer maxsizes, without having to manually modify it? Also, I do not understand the need for the `_nodebug` versions of the BLI_string functions, can you explain more in details? Finally, agree with your notes regarding naming. In fact, could even use a more generic name (`WITH_BUFFER_SIZE_DEBUG` ?), and in the future we could have our own `memcpy` wrapper that would perform the same type of checks too?
Author
Owner

While I see the point of the patch, I am not so convinced by the solution proposed here.

Yep, it's a judgement call, without something like this - we get on mostly OK, but there is a high chance these kinds of errors get re-introduced and we don't notice ... arguably if we don't notice they can't be that bad. On the other hand, users don't report every bug they run into and if they do, these kinds of errors take time to track down. This patch has the advantage of being able to catch them early, avoiding them to begin with.

Having to add such clutter to all RNA string accessors does not really sounds good to me, to say the least. Not to mention that other places in code would most likely need such checks too? Which implies also the need to manually identify such places, etc.

It's not all access functions, only ones that call into functions that expect fixed sized buffers.

Is there a reason (when the debug option is on) not to e.g. systematically write (or even read actually) the whole allowed size in destination buffer in BLI_string functions? This should trigger ASAN & co just as well, and ensures all code calling BLI_string copy etc. functions is checked for proper buffer maxsizes, without having to manually modify it?

Not sure what you mean by having to manually modify it. From what your writing, this patch is writing the whole allowed size, so I'm not sure what your suggesting be different.

Also, I do not understand the need for the _nodebug versions of the BLI_string functions, can you explain more in details?

RNA_property_string_get_alloc does the following.

  • length = RNA_property_string_length(..)
  • buf = MEM_mallocN(length + 1)
  • RNA_property_string_get(..., buf);

This means the buffer length is exactly the size needed.

Then if the internal RNA _get() callback uses: BLI_strncpy(buf, id->name + 2, MAX_ID_NAME - 2); for example, the destination buffer is allocated memory of size: strlen(id->name + 2) + 1 not MAX_ID_NAME - 2.
So the length argument is technically wrong but as the caller is expected to use strlen first, it turns out not to matter unless DEBUG_STRSIZE is enabled and the full buffer size is written to. If the string weren't nil terminated there would be a difference, but we don't support un-terminated strings from makesrna.c (generated code calls strlen(..) on these strings so they have to be terminated).

Finally, agree with your notes regarding naming. In fact, could even use a more generic name (WITH_BUFFER_SIZE_DEBUG ?), and in the future we could have our own memcpy wrapper that would perform the same type of checks too?

This seems fine, I wouldn't mind updating the patch if other issues are resolved and it's generally an acceptable approach.

> While I see the point of the patch, I am not so convinced by the solution proposed here. Yep, it's a judgement call, without something like this - we get on mostly OK, but there is a high chance these kinds of errors get re-introduced and we don't notice ... arguably if we don't notice they can't be that bad. On the other hand, users don't report every bug they run into and if they do, these kinds of errors take time to track down. This patch has the advantage of being able to catch them early, avoiding them to begin with. > Having to add such clutter to all RNA string accessors does not really sounds good to me, to say the least. Not to mention that other places in code would most likely need such checks too? Which implies also the need to manually identify such places, etc. It's not all access functions, only ones that call into functions that expect fixed sized buffers. > Is there a reason (when the debug option is on) not to e.g. systematically write (or even read actually) the whole allowed size in destination buffer in BLI_string functions? This should trigger ASAN & co just as well, and ensures all code calling BLI_string copy etc. functions is checked for proper buffer maxsizes, without having to manually modify it? Not sure what you mean by having to manually modify it. From what your writing, this patch is writing the whole allowed size, so I'm not sure what your suggesting be different. > Also, I do not understand the need for the `_nodebug` versions of the BLI_string functions, can you explain more in details? `RNA_property_string_get_alloc` does the following. - `length = RNA_property_string_length(..)` - `buf = MEM_mallocN(length + 1)` - `RNA_property_string_get(..., buf);` This means the buffer length is exactly the size needed. Then if the internal RNA `_get()` callback uses: `BLI_strncpy(buf, id->name + 2, MAX_ID_NAME - 2);` for example, the destination buffer is allocated memory of size: `strlen(id->name + 2) + 1` not `MAX_ID_NAME - 2`. So the length argument is technically wrong but as the caller is expected to use `strlen` first, it turns out not to matter unless `DEBUG_STRSIZE` is enabled and the full buffer size is written to. If the string weren't nil terminated there would be a difference, but we don't support un-terminated strings from `makesrna.c` (generated code calls `strlen(..)` on these strings so they have to be terminated). > Finally, agree with your notes regarding naming. In fact, could even use a more generic name (`WITH_BUFFER_SIZE_DEBUG` ?), and in the future we could have our own `memcpy` wrapper that would perform the same type of checks too? > This seems fine, I wouldn't mind updating the patch if other issues are resolved and it's generally an acceptable approach.
Brecht Van Lommel requested changes 2023-05-04 20:06:12 +02:00
CMakeLists.txt Outdated
@ -654,0 +655,4 @@
Ensure string operations on fixed size buffers \
(works well with with \"WITH_COMPILER_ASAN\" & valgrind to detect incorrect buffer size arguments)"
OFF)
mark_as_advanced(WITH_STRSIZE_DEBUG)

Do you think we could enable this in build_files/cmake/config/blender_developer.cmake?

There is a performance impact, but if ASAN is on as well it's not a big deal I guess.

I'd even consider just always enabling this when ASAN is used, and not even having a CMake option.

Do you think we could enable this in `build_files/cmake/config/blender_developer.cmake`? There is a performance impact, but if ASAN is on as well it's not a big deal I guess. I'd even consider just always enabling this when ASAN is used, and not even having a CMake option.
Author
Owner

Enabled in blender_developer.cmake, I'd rather keep it a separate option though for a couple of reasons.

  • Buffer overruns within a struct don't generate errors with ASAN, so it's useful to be able to turn it off to check if a corruption was caused by data being written past the string but within a struct.
  • This can be used with valgrind too.
Enabled in `blender_developer.cmake`, I'd rather keep it a separate option though for a couple of reasons. - Buffer overruns within a struct don't generate errors with ASAN, so it's useful to be able to turn it off to check if a corruption was caused by data being written past the string but within a struct. - This can be used with valgrind too.
@ -738,2 +738,2 @@
"BLI_strncpy" :
"BLI_strncpy_utf8";
"BLI_strncpy_nodebug" :
"BLI_strncpy_utf8_nodebug";

This could always be just strcpy I think? Checking the length of the source string does not seem helpful, and value should have the appropriate size.

This could always be just `strcpy` I think? Checking the length of the source string does not seem helpful, and `value` should have the appropriate size.
Author
Owner

Replaced BLI_strncpy & BLI_strncpy_utf8 with strcpy, also double checked BLI_strncpy_utf8 wasn't doing anything besides not copying a partial utf8 character when the string size is limited.

The sizes passed to BLI_strncpy have been moved to assertions in debug mode to they remain valid.

Replaced `BLI_strncpy` & `BLI_strncpy_utf8` with `strcpy`, also double checked `BLI_strncpy_utf8` wasn't doing anything besides not copying a partial utf8 character when the string size is limited. The sizes passed to BLI_strncpy have been moved to assertions in debug mode to they remain valid.
@ -1216,7 +1216,13 @@ static StructRNA *rna_wmKeyConfigPref_refine(PointerRNA *ptr)
static void rna_wmKeyMapItem_idname_get(PointerRNA *ptr, char *value)
{
wmKeyMapItem *kmi = ptr->data;
# ifdef DEBUG_STRSIZE

For these cases, I would remove the #ifdef, add a comment instead and always do the extra copy.

This is not performance critical, and in some way I think the code can be considered to be more correct that way.

For these cases, I would remove the #ifdef, add a comment instead and always do the extra copy. This is not performance critical, and in some way I think the code can be considered to be more correct that way.
Author
Owner

Done.

Done.
Campbell Barton force-pushed pr-debug-strsize from 8a3b53ed8e to 47e9a4f62c 2023-05-05 06:59:15 +02:00 Compare
Campbell Barton force-pushed pr-debug-strsize from 47e9a4f62c to 0e853e746f 2023-05-05 07:01:13 +02:00 Compare
Author
Owner

Updated the patch:

  • Removed *_debug() versions of string copying functions, use strcpy in RNA.
  • Removed BLI_strncpy calls from RNA callbacks in main, use fixed size buffers in a couple of places.
Updated the patch: - Removed `*_debug()` versions of string copying functions, use strcpy in RNA. - Removed `BLI_strncpy` calls from RNA callbacks in `main`, use fixed size buffers in a couple of places.
Campbell Barton requested review from Brecht Van Lommel 2023-05-05 07:21:31 +02:00
Campbell Barton force-pushed pr-debug-strsize from 0e853e746f to 57e6dfe122 2023-05-05 07:22:44 +02:00 Compare
Campbell Barton force-pushed pr-debug-strsize from 57e6dfe122 to 8b7c31137a 2023-05-05 07:26:44 +02:00 Compare
Author
Owner

@blender-bot build

@blender-bot build
Campbell Barton force-pushed pr-debug-strsize from 8b7c31137a to 16f43c8dcd 2023-05-05 07:38:10 +02:00 Compare
Brecht Van Lommel approved these changes 2023-05-05 12:39:52 +02:00
Bastien Montagne approved these changes 2023-05-06 16:59:18 +02:00
Bastien Montagne left a comment
Owner

Ah, did not know (or remember) that DEBUG_STRSIZE was already a thing in existing code... now things make much more sense.

Patch LGTM too.

Ah, did not know (or remember) that `DEBUG_STRSIZE` was already a thing in existing code... now things make much more sense. Patch LGTM too.
Author
Owner

Committed 7f8495c44b, closing.

Committed 7f8495c44b48b2995e45419bdd4149896eec536d, closing.
Campbell Barton closed this pull request 2023-05-07 06:47:35 +02:00

Pull request closed

Sign in to join this conversation.
No Label
Interest
Alembic
Interest
Animation & Rigging
Interest
Asset Browser
Interest
Asset Browser Project Overview
Interest
Audio
Interest
Automated Testing
Interest
Blender Asset Bundle
Interest
BlendFile
Interest
Collada
Interest
Compatibility
Interest
Compositing
Interest
Core
Interest
Cycles
Interest
Dependency Graph
Interest
Development Management
Interest
EEVEE
Interest
EEVEE & Viewport
Interest
Freestyle
Interest
Geometry Nodes
Interest
Grease Pencil
Interest
ID Management
Interest
Images & Movies
Interest
Import Export
Interest
Line Art
Interest
Masking
Interest
Metal
Interest
Modeling
Interest
Modifiers
Interest
Motion Tracking
Interest
Nodes & Physics
Interest
OpenGL
Interest
Overlay
Interest
Overrides
Interest
Performance
Interest
Physics
Interest
Pipeline, Assets & IO
Interest
Platforms, Builds & Tests
Interest
Python API
Interest
Render & Cycles
Interest
Render Pipeline
Interest
Sculpt, Paint & Texture
Interest
Text Editor
Interest
Translations
Interest
Triaging
Interest
Undo
Interest
USD
Interest
User Interface
Interest
UV Editing
Interest
VFX & Video
Interest
Video Sequencer
Interest
Virtual Reality
Interest
Vulkan
Interest
Wayland
Interest
Workbench
Interest: X11
Legacy
Blender 2.8 Project
Legacy
Milestone 1: Basic, Local Asset Browser
Legacy
OpenGL Error
Meta
Good First Issue
Meta
Papercut
Meta
Retrospective
Meta
Security
Module
Animation & Rigging
Module
Core
Module
Development Management
Module
EEVEE & Viewport
Module
Grease Pencil
Module
Modeling
Module
Nodes & Physics
Module
Pipeline, Assets & IO
Module
Platforms, Builds & Tests
Module
Python API
Module
Render & Cycles
Module
Sculpt, Paint & Texture
Module
Triaging
Module
User Interface
Module
VFX & Video
Platform
FreeBSD
Platform
Linux
Platform
macOS
Platform
Windows
Priority
High
Priority
Low
Priority
Normal
Priority
Unbreak Now!
Status
Archived
Status
Confirmed
Status
Duplicate
Status
Needs Info from Developers
Status
Needs Information from User
Status
Needs Triage
Status
Resolved
Type
Bug
Type
Design
Type
Known Issue
Type
Patch
Type
Report
Type
To Do
No Milestone
No project
No Assignees
3 Participants
Notifications
Due Date
The due date is invalid or out of range. Please use the format 'yyyy-mm-dd'.

No due date set.

Dependencies

No dependencies set.

Reference: blender/blender#107602
No description provided.