-
Notifications
You must be signed in to change notification settings - Fork 9
Description
Summary
Intermittent native crash (0xC0000005 — ACCESS_VIOLATION) in Adobe AIR.dll during application startup when flash.sampler.* APIs are used early in the app lifecycle. The crash does not occur every time — the same build may crash on one launch and work perfectly on the next, with no code changes.
Environment
- AIR SDK: 51.1.3.10
- Platform: Windows 11 Pro (10.0.26200), x86 (32-bit ADL)
- GPU Driver: DirectX 11 (Standard Extended profile)
- Launch method:
adl.exe -profile extendedDesktop
Windows Event Log
Faulting application: adl.exe, version: 51.1.3.10, timestamp: 0x67e42a03
Faulting module: Adobe AIR.dll, version: 51.1.3.10, timestamp: 0x67e42c3f
Exception code: 0xc0000005
Fault offset: 0x000b8a71
Binary Analysis of the Crash Site
I disassembled Adobe AIR.dll at the faulting offset. The crash is inside an internal sampler record parser function (not exported, starts at RVA 0x000B8A08):
; Function: parses individual sample records from the GC sampler buffer
; Signature: void parseSampleRecord(SampleRecord* out [esi], uint8** cursor [edx])
0x000B8A08: push esi
0x000B8A09: mov esi, [esp+0xC] ; out struct (48 bytes)
0x000B8A0D: push 0x30
0x000B8A0F: push 0
0x000B8A11: push esi
0x000B8A12: call memset ; zero-init output struct
; Read first pair (8 bytes) from cursor
0x000B8A1E: mov ecx, [edx] ; ecx = current stream position
0x000B8A20: mov eax, [ecx] ; read dword 1
0x000B8A22: mov [esi], eax
0x000B8A24: mov eax, [ecx+4] ; read dword 2
0x000B8A27: mov [esi+4], eax
0x000B8A2A: add dword ptr [edx], 8 ; advance cursor
; Read type tag
0x000B8A2F: mov eax, [[edx]]
0x000B8A31: mov [esi+8], eax ; store type tag
0x000B8A34: add dword ptr [edx], 4
; Branch on type tag sentinel values:
0x000B8A37: cmp [esi+8], 0xDDDDDDDD ; stack-trace sample?
0x000B8A62: cmp [esi+8], 0x55555555 ; DeleteObjectSample? → skip to end
0x000B8A7F: cmp [esi+8], 0xAAAAAAAA ; NewObjectSample?
0x000B8A8A: cmp [esi+8], 0xEEEEEEEE ; other sample type?
; >>> CRASH HERE: reading next record data
0x000B8A6F: mov ecx, [edx] ; ecx = current cursor position
0x000B8A71: mov eax, [ecx] ; CRASH! ecx is NULL or invalidThe function has 3 internal callers (at RVAs 0x000B8831, 0x000B8B81, 0x0045045A), all in sampler iteration loops. The caller at 0x000B8831 checks for 0xAAAAAAAA (NewObjectSample) immediately after the call, confirming this is the avmplus sampler subsystem.
Root Cause Analysis
The crash occurs because the sampler buffer read cursor ([edx]) points past valid data or into uninitialized memory. This is a race condition during early startup:
- Application calls
sampleInternalAllocs(true)+startSampling()+setSamplerCallback()early in initialization - The GC immediately begins writing sample records into the internal buffer
- The sampler callback fires (or the runtime iterates the buffer internally) before the buffer management is fully stabilized
- The cursor reads beyond valid data →
ACCESS_VIOLATION
The intermittent nature confirms a timing-dependent race: sometimes the runtime initializes fast enough, sometimes it doesn't.
Minimal Reproduction
package {
import flash.display.Sprite;
import flash.sampler.sampleInternalAllocs;
import flash.sampler.startSampling;
import flash.sampler.setSamplerCallback;
import flash.sampler.getSamples;
import flash.sampler.clearSamples;
public class SamplerCrashRepro extends Sprite {
public function SamplerCrashRepro() {
// Start sampler immediately at construction time
sampleInternalAllocs(true);
startSampling();
setSamplerCallback(onSamplerFull);
// Allocate objects to fill the sampler buffer quickly
for (var i:int = 0; i < 10000; i++) {
new Object();
}
}
private function onSamplerFull():void {
for each (var s:* in getSamples()) { /* process */ }
clearSamples();
}
}
}Note: The crash is non-deterministic. It may take 5-20 launches to reproduce. Using adl.exe with -profile extendedDesktop and ANE extensions loaded increases the likelihood, possibly due to additional initialization work competing with the sampler.
Workaround
Delaying sampler initialization by ~500ms via setTimeout avoids the race condition:
// Instead of immediate init:
setTimeout(function():void {
sampleInternalAllocs(true);
startSampling();
setSamplerCallback(onSamplerFull);
}, 500);Expected Behavior
Calling startSampling() + setSamplerCallback() at any point during application startup should be safe and not cause a native crash.
Additional Notes
mm.cfghasAS3Sampling=1andAS3AutoStartSampling=1(these are safe and do NOT trigger the MemoryTelemetrySampler conflict)- The SWF is not compiled with
-advanced-telemetry(which would create a conflictingMemoryTelemetrySampler) .telemetry.cfgonly hasTelemetryAddress(noSamplerEnabledorCPUCaptureflags)- The crash is in the
.textsection at a non-exported internal function — no debug symbols available for Adobe AIR.dll