Skip to content

Commit 2036aa3

Browse files
committed
[cpp] Fix double free crash in SkeletonBinary::readSkeletonDataFile, add terminal logging utilities and style guide, add nostdcpp
1 parent aaca02a commit 2036aa3

File tree

9 files changed

+433
-153
lines changed

9 files changed

+433
-153
lines changed

.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -254,3 +254,6 @@ spine-c/codegen/spine-cpp-types.json
254254
spine-flutter/example/devtools_options.yaml
255255
spine-glfw/.cache
256256
formatters/eclipse-formatter/format-diff.txt
257+
spine-cpp/build-debug
258+
spine-cpp/build-linux
259+
spine-cpp/build-release-debug

formatters/logging/bash-colors.sh

Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
#!/bin/bash
2+
# Bash color and formatting utilities
3+
# Source this file in your bash scripts for colored output
4+
5+
# Colors
6+
RED='\033[0;31m'
7+
GREEN='\033[0;32m'
8+
YELLOW='\033[0;33m'
9+
BLUE='\033[0;34m'
10+
MAGENTA='\033[0;35m'
11+
CYAN='\033[0;36m'
12+
WHITE='\033[0;37m'
13+
GRAY='\033[0;90m'
14+
15+
# Bright colors
16+
BRIGHT_RED='\033[0;91m'
17+
BRIGHT_GREEN='\033[0;92m'
18+
BRIGHT_YELLOW='\033[0;93m'
19+
BRIGHT_BLUE='\033[0;94m'
20+
BRIGHT_MAGENTA='\033[0;95m'
21+
BRIGHT_CYAN='\033[0;96m'
22+
BRIGHT_WHITE='\033[0;97m'
23+
24+
# Background colors
25+
BG_RED='\033[41m'
26+
BG_GREEN='\033[42m'
27+
BG_YELLOW='\033[43m'
28+
BG_BLUE='\033[44m'
29+
BG_MAGENTA='\033[45m'
30+
BG_CYAN='\033[46m'
31+
BG_WHITE='\033[47m'
32+
33+
# Text styles
34+
BOLD='\033[1m'
35+
DIM='\033[2m'
36+
UNDERLINE='\033[4m'
37+
BLINK='\033[5m'
38+
REVERSE='\033[7m'
39+
STRIKETHROUGH='\033[9m'
40+
41+
# Reset
42+
NC='\033[0m' # No Color
43+
44+
# Design principles:
45+
# 1. Minimal visual noise - use color sparingly for emphasis
46+
# 2. Clear hierarchy - different levels of information have different treatments
47+
# 3. Consistent spacing - clean vertical rhythm
48+
# 4. Accessible - readable without colors
49+
50+
# Main header for script/tool name
51+
log_title() {
52+
echo ""
53+
echo -e "${BOLD}$1${NC}"
54+
echo ""
55+
}
56+
57+
# Section headers for major phases
58+
log_section() {
59+
echo -e "${BOLD}${BLUE}$1${NC}"
60+
}
61+
62+
# Individual actions/steps
63+
log_action() {
64+
echo -e " $1..."
65+
}
66+
67+
# Results - success/failure/info
68+
log_ok() {
69+
echo -e " ${GREEN}${NC} $1"
70+
}
71+
72+
log_fail() {
73+
echo -e " ${RED}${NC} $1"
74+
}
75+
76+
log_warn() {
77+
echo -e " ${YELLOW}!${NC} $1"
78+
}
79+
80+
log_skip() {
81+
echo -e " ${GRAY}-${NC} $1"
82+
}
83+
84+
# Final summary
85+
log_summary() {
86+
echo ""
87+
echo -e "${BOLD}$1${NC}"
88+
}
89+
90+
# Detailed output (errors, etc.)
91+
log_detail() {
92+
echo -e "${GRAY}$1${NC}"
93+
}
Lines changed: 153 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,153 @@
1+
# Terminal Logging Style Guide
2+
3+
This guide defines the terminal output style for all bash scripts in the Spine Runtimes project.
4+
5+
## Design Principles
6+
7+
1. **Minimal visual noise** - Use color sparingly for emphasis, not decoration
8+
2. **Clear hierarchy** - Different levels of information have distinct visual treatments
9+
3. **Consistent spacing** - Clean vertical rhythm throughout output
10+
4. **Accessible** - Readable and meaningful even without colors
11+
5. **Scannable** - Easy to quickly identify successes, failures, and important information
12+
13+
## Visual Hierarchy
14+
15+
### 1. Title (`log_title`)
16+
- **Purpose**: Main script/tool name
17+
- **Style**: Bold with vertical spacing
18+
- **Usage**: Once at the beginning of script execution
19+
20+
```bash
21+
log_title "Spine-C++ Test"
22+
```
23+
24+
### 2. Section (`log_section`)
25+
- **Purpose**: Major phases or groups of operations
26+
- **Style**: Bold blue text, no extra spacing
27+
- **Usage**: Build, Test, Deploy, etc.
28+
29+
```bash
30+
log_section "Build"
31+
log_section "Test"
32+
```
33+
34+
### 3. Action (`log_action`)
35+
- **Purpose**: Individual operations in progress
36+
- **Style**: Indented, followed by "..."
37+
- **Usage**: Before starting an operation
38+
39+
```bash
40+
log_action "Building all variants"
41+
log_action "Testing headless-test"
42+
```
43+
44+
### 4. Results
45+
- **Purpose**: Outcome of operations
46+
- **Style**: Indented with colored symbols
47+
48+
```bash
49+
log_ok "Build completed" # Green ✓
50+
log_fail "Build failed" # Red ✗
51+
log_warn "Deprecated feature" # Yellow !
52+
log_skip "Not supported on macOS" # Gray -
53+
```
54+
55+
### 5. Detail (`log_detail`)
56+
- **Purpose**: Secondary information, error output, debug info
57+
- **Style**: Gray text, indented
58+
- **Usage**: Additional context, error messages
59+
60+
```bash
61+
log_detail "Platform: Darwin"
62+
log_detail "$ERROR_OUTPUT"
63+
```
64+
65+
### 6. Summary (`log_summary`)
66+
- **Purpose**: Final result or conclusion
67+
- **Style**: Bold with vertical spacing
68+
- **Usage**: End of script execution
69+
70+
```bash
71+
log_summary "✓ All tests passed (5/5)"
72+
log_summary "✗ Tests failed (3/5)"
73+
```
74+
75+
## Complete Example
76+
77+
```bash
78+
#!/bin/bash
79+
source ../formatters/bash-colors.sh
80+
81+
log_title "Spine-C++ Test"
82+
log_detail "Platform: $(uname)"
83+
84+
log_section "Build"
85+
log_action "Building all variants"
86+
if BUILD_OUTPUT=$(./build.sh clean release 2>&1); then
87+
log_ok "Build completed"
88+
else
89+
log_fail "Build failed"
90+
log_detail "$BUILD_OUTPUT"
91+
exit 1
92+
fi
93+
94+
log_section "Test"
95+
log_action "Testing headless-test"
96+
if test_result; then
97+
log_ok "headless-test"
98+
else
99+
log_fail "headless-test - execution failed"
100+
log_detail "$error_output"
101+
fi
102+
103+
log_summary "✓ All tests passed (2/2)"
104+
```
105+
106+
## Output Preview
107+
108+
```
109+
Spine-C++ Test
110+
111+
Platform: Darwin
112+
113+
Build
114+
Building all variants...
115+
✓ Build completed
116+
117+
Test
118+
Testing headless-test...
119+
✓ headless-test
120+
Testing headless-test-nostdcpp...
121+
✓ headless-test-nostdcpp
122+
123+
✓ All tests passed (2/2)
124+
```
125+
126+
## Error Handling Best Practices
127+
128+
1. **Capture output**: Use `OUTPUT=$(command 2>&1)` to capture both stdout and stderr
129+
2. **Check exit codes**: Always check if critical operations succeeded
130+
3. **Show details on failure**: Use `log_detail` to show error output
131+
4. **Fail fast**: Exit immediately on critical failures
132+
5. **Clear error messages**: Make failure reasons obvious
133+
134+
```bash
135+
if BUILD_OUTPUT=$(./build.sh clean release 2>&1); then
136+
log_ok "Build completed"
137+
else
138+
log_fail "Build failed"
139+
log_detail "$BUILD_OUTPUT"
140+
exit 1
141+
fi
142+
```
143+
144+
## Usage
145+
146+
1. Source the utilities in your script:
147+
```bash
148+
source ../formatters/logging/bash-colors.sh
149+
```
150+
151+
2. Follow the hierarchy patterns shown above
152+
3. Use appropriate functions for each type of output
153+
4. Test output both with and without color support

spine-cpp/CMakeLists.txt

Lines changed: 31 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,11 @@ option(SPINE_NO_FILE_IO "Disable file I/O operations" OFF)
77

88
include_directories(include)
99
file(GLOB INCLUDES "include/**/*.h")
10-
file(GLOB SOURCES "src/**/*.cpp")
10+
file(GLOB ALL_SOURCES "src/**/*.cpp")
11+
12+
# Exclude nostdcpp.cpp from regular build
13+
list(FILTER ALL_SOURCES EXCLUDE REGEX "src/nostdcpp\\.cpp$")
14+
set(SOURCES ${ALL_SOURCES})
1115

1216
add_library(spine-cpp STATIC ${SOURCES} ${INCLUDES})
1317
target_include_directories(spine-cpp PUBLIC include)
@@ -17,7 +21,7 @@ if(SPINE_NO_FILE_IO)
1721
endif()
1822

1923
# nostdcpp variant (no C++ standard library)
20-
file(GLOB NOSTDCPP_SOURCES ${SOURCES} "src/nostdlib.cpp")
24+
set(NOSTDCPP_SOURCES ${SOURCES} "src/nostdcpp.cpp")
2125
add_library(spine-cpp-nostdcpp STATIC ${NOSTDCPP_SOURCES} ${INCLUDES})
2226
target_include_directories(spine-cpp-nostdcpp PUBLIC include)
2327

@@ -35,28 +39,39 @@ export(
3539
if(CMAKE_SOURCE_DIR STREQUAL CMAKE_CURRENT_SOURCE_DIR)
3640
add_executable(headless-test ${CMAKE_CURRENT_SOURCE_DIR}/tests/HeadlessTest.cpp)
3741
target_link_libraries(headless-test spine-cpp)
38-
42+
3943
if(SPINE_NO_FILE_IO)
4044
target_compile_definitions(headless-test PRIVATE SPINE_NO_FILE_IO)
4145
endif()
42-
43-
# nostdcpp test executable (no C++ stdlib)
46+
47+
# Configure nostdcpp linking for different platforms
4448
add_executable(headless-test-nostdcpp ${CMAKE_CURRENT_SOURCE_DIR}/tests/HeadlessTest.cpp)
45-
49+
target_link_libraries(headless-test-nostdcpp spine-cpp-nostdcpp)
50+
4651
if(MSVC)
47-
# On Windows/MSVC, disable default libraries but keep C runtime
48-
target_link_libraries(headless-test-nostdcpp spine-cpp-nostdcpp)
4952
target_link_options(headless-test-nostdcpp PRIVATE /NODEFAULTLIB)
5053
target_link_libraries(headless-test-nostdcpp msvcrt kernel32)
54+
elseif(CMAKE_CXX_COMPILER_ID MATCHES "Clang")
55+
target_link_options(headless-test-nostdcpp PRIVATE -nostdlib++ -lc)
5156
else()
52-
# Unix/Linux: avoid linking libstdc++ automatically
53-
if(CMAKE_CXX_COMPILER_ID MATCHES "Clang")
54-
target_link_libraries(headless-test-nostdcpp spine-cpp-nostdcpp)
55-
target_link_options(headless-test-nostdcpp PRIVATE -nostdlib++ -lc)
56-
else()
57-
# GCC: use -nodefaultlibs and link minimal libraries including libgcc for operator new/delete
58-
target_link_options(headless-test-nostdcpp PRIVATE -nodefaultlibs)
59-
target_link_libraries(headless-test-nostdcpp spine-cpp-nostdcpp -lm -lc -lgcc)
57+
target_link_options(headless-test-nostdcpp PRIVATE -nodefaultlibs)
58+
target_link_libraries(headless-test-nostdcpp -lm -lc -lgcc)
59+
endif()
60+
61+
# Static variants (Linux only)
62+
if(UNIX AND NOT APPLE)
63+
add_executable(headless-test-static ${CMAKE_CURRENT_SOURCE_DIR}/tests/HeadlessTest.cpp)
64+
target_link_libraries(headless-test-static spine-cpp)
65+
target_link_options(headless-test-static PRIVATE -static)
66+
67+
add_executable(headless-test-nostdcpp-static ${CMAKE_CURRENT_SOURCE_DIR}/tests/HeadlessTest.cpp)
68+
target_link_libraries(headless-test-nostdcpp-static spine-cpp-nostdcpp)
69+
target_link_options(headless-test-nostdcpp-static PRIVATE -static -static-libgcc -Wl,--exclude-libs,libstdc++.a)
70+
target_link_libraries(headless-test-nostdcpp-static -lm -lc)
71+
72+
if(SPINE_NO_FILE_IO)
73+
target_compile_definitions(headless-test-static PRIVATE SPINE_NO_FILE_IO)
74+
target_compile_definitions(headless-test-nostdcpp-static PRIVATE SPINE_NO_FILE_IO)
6075
endif()
6176
endif()
6277
endif()

spine-cpp/src/nostdcpp.cpp

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
/******************************************************************************
2+
* Spine Runtimes License Agreement
3+
* Last updated April 5, 2025. Replaces all prior versions.
4+
*
5+
* Copyright (c) 2013-2025, Esoteric Software LLC
6+
*
7+
* Integration of the Spine Runtimes into software or otherwise creating
8+
* derivative works of the Spine Runtimes is permitted under the terms and
9+
* conditions of Section 2 of the Spine Editor License Agreement:
10+
* http://esotericsoftware.com/spine-editor-license
11+
*
12+
* Otherwise, it is permitted to integrate the Spine Runtimes into software
13+
* or otherwise create derivative works of the Spine Runtimes (collectively,
14+
* "Products"), provided that each user of the Products must obtain their own
15+
* Spine Editor license and redistribution of the Products in any form must
16+
* include this license and copyright notice.
17+
*
18+
* THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY
19+
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
20+
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
21+
* DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY
22+
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
23+
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,
24+
* BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND
25+
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26+
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
27+
* THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28+
*****************************************************************************/
29+
30+
#include <cstddef>
31+
32+
// Stubs for C++ stdlib functions spine-cpp depends on. Used for nostdcpp builds.
33+
// These are weak symbols to allow overriding in custom builds, e.g. headless-test-nostdcpp
34+
// where the main app still requires C++.
35+
36+
extern "C" {
37+
void* malloc(size_t size);
38+
void free(void* ptr);
39+
}
40+
41+
__attribute__((weak)) void* operator new(size_t size) {
42+
return malloc(size);
43+
}
44+
45+
__attribute__((weak)) void operator delete(void* ptr) {
46+
if (ptr) free(ptr);
47+
}
48+
49+
extern "C" __attribute__((weak)) int __cxa_guard_acquire(char* guard) {
50+
return *guard == 0 ? (*guard = 1, 1) : 0;
51+
}
52+
53+
extern "C" __attribute__((weak)) void __cxa_guard_release(char* guard) {
54+
// No-op for single-threaded
55+
(void)guard;
56+
}
57+
58+
extern "C" __attribute__((weak)) void __cxa_pure_virtual() {
59+
}
60+
61+
extern "C" __attribute__((weak)) char __stack_chk_guard = 0;
62+
extern "C" __attribute__((weak)) void __stack_chk_fail() {
63+
}

0 commit comments

Comments
 (0)