AD6002: EliminateDuplicateStrings¶
Summary¶
| Property | Value |
|---|---|
| ID | AD6002 |
| Name | EliminateDuplicateStrings |
| Category | Performance |
| Severity | Warning |
| Applies to | PE (Windows) |
Description¶
This rule checks that PE binaries were compiled with the /GF (Eliminate Duplicate Strings) option enabled. String pooling reduces binary size and can improve performance by ensuring identical string literals share the same memory.
Why This Matters¶
String pooling is a simple optimization with measurable binary size reduction. Without it, identical string literals are duplicated throughout the binary, wasting memory and reducing cache efficiency.
The Duplication Problem¶
// File1.c
printf("Error: %s\n", msg); // "Error: %s\n" stored
// File2.c
printf("Error: %s\n", other); // "Error: %s\n" stored AGAIN
// File3.c
printf("Error: %s\n", val); // "Error: %s\n" stored AGAIN
// Without /GF: 3 copies of same string
// With /GF: 1 copy, 3 references
Size Impact¶
| Binary Type | Typical Savings |
|---|---|
| Small apps | 1-5% |
| Large apps | 3-10% |
| Localized apps | 5-15% (many strings) |
| Debug builds | Often more |
Cache Efficiency¶
Without string pooling:
0x1000: "Error: %s\n" (file1.c)
0x2000: "Error: %s\n" (file2.c)
0x3000: "Error: %s\n" (file3.c)
Each access may miss cache
With string pooling:
0x1000: "Error: %s\n" (all files)
Single location, stays in cache
Implied by Optimization¶
String pooling is enabled by optimization flags:
| Flag | /GF Status |
|---|---|
| /O1 | Implied |
| /O2 | Implied |
| /Ox | Implied |
| /GF explicit | Direct |
| None | Not enabled |
Security Consideration¶
Larger binary:
- More code/data pages
- Larger attack surface (more gadgets)
- Slower load time
Smaller binary (with /GF):
- Fewer pages
- Smaller attack surface
- Faster load
Build Configuration Indicator¶
Missing /GF often indicates misconfigured release builds:
Expected: Release build with /O2 (implies /GF)
Found: No string pooling
Probable cause:
- Debug build shipped as release
- Optimization accidentally disabled
- Build system misconfiguration
- Smaller binaries: Duplicate strings are stored only once
- Cache efficiency: Less memory used for string constants
- Optimization indicator:
/GFis implied by/O1,/O2, and/Ox - Release build verification: Helps ensure proper release build configuration
How to Fix¶
Enable string pooling¶
Visual Studio¶
- Project Properties → C/C++ → Code Generation
- Set "Enable String Pooling" to "Yes (/GF)"
Or enable optimization which implies string pooling: 1. Project Properties → C/C++ → Optimization 2. Set "Optimization" to "Maximize Speed (/O2)" or "Full Optimization (/Ox)"
CMake¶
Detection Method¶
aldur detects string pooling by examining compiler command lines stored in PDB debug information. The rule looks for:
- Explicit /GF flag
- Optimization flags that imply /GF: /O1, /O2, /Ox
Example¶
Warning: String pooling not enabled
Pass: String pooling enabled
Relationship with Optimization¶
| Flag | String Pooling | Notes |
|---|---|---|
/GF |
✅ Explicit | Directly enables |
/O1 |
✅ Implied | Minimize size |
/O2 |
✅ Implied | Maximize speed |
/Ox |
✅ Implied | Full optimization |
/Od |
❌ | Debug, no optimization |