Skip to content

[BUG]: Crash #27

Description

@nickknyc

details via Codex (Sol Extra High, which I have been using for all audio work including building the driver and all the installs etc. )

Windows Version

26200.8737

PC Information

HOmebre, i9, nVidia 3080, 64gb ram

Processor Architecture

x64 (AMD / Intel etc.)

Audio Interface

Tascam Model 12

Audio Interface Connection

Desktop case USB connection not directly on the motherboard back panel

Sample Rate

48k

Buffer Size

No response

Application in use

unreal engine had been loaded

Audio Mode

Unknown or unsure

Type of bug

Windows Crash or green/blue/black Screen

Link to glitch trace

No response

Steps to reproduce

Image

Expected behavior

No response

Additional notes

Filing-ready GitHub issue

Proposed title

[BUG]: Repeated 0x7E BSOD from divide-by-zero in TransferObject::CalculateEstimatedQPCPosition

Windows Version

Windows 11 Pro 25H2, x64, build 26200.8737 (10.0.26200).

PC Information

Self-built desktop using a Gigabyte Technology Z590I VISION D motherboard.

Processor Architecture

x64 (AMD / Intel etc.)

Audio Interface

TASCAM Model 12.

  • USB hardware ID: USB\VID_0644&PID_805F&MI_00
  • Device instance observed after the latest reboot:
    USB\VID_0644&PID_805F&MI_00\7&FAA69BA&0&0000

Audio Interface Connection

Through a USB hub

The Model 12 is currently enumerated below a generic VIA Labs USB 2.0 hub:

  • Hub ID: USB\VID_2109&PID_2211
  • Hub description: USB2.0 Hub
  • Topology: xHCI root hub -> port 9 -> USB 2.0 hub -> port 1 -> Model 12

The physical hub brand/model is not exposed by Windows.

Sample Rate

48 kHz on the Windows playback and capture endpoints and in the applications
whose rate was configurable.

Buffer Size

1024 samples in Guitar Pro during one incident that preceded a crash. The
buffer size at the exact instant of all three bugchecks is not known.

Application in use

The kernel crash is intermittent and is not isolated to one application. The
most specific observed application sequence was:

  1. Guitar Pro 8.1.5 used the Model 12 through PortAudio's Standard /
    Primary Sound Driver path.
  2. Guitar Pro was closed.
  3. A browser was opened to play YouTube through the Model 12.
  4. Playback initially remained loading, then produced abnormal sounds, and
    recovered roughly one minute later.

Guitar Pro logged 44 occurrences of Pa_StopStream(d->stream) followed by
Pa Error :: Unanticipated host error during that sequence. A matching 0x7E
bugcheck occurred later that day. This preceding symptom may be related, but
it is not a deterministic user-level reproduction and causality has not been
established.

Audio Mode

Windows Audio (WASAPI etc.)

The browser used normal Windows audio. Guitar Pro reported PortAudio
Standard / Primary Sound Driver. No ASIO application is required for the
confirmed driver fault.

Type of bug

  • Windows Crash or green/blue/black Screen
  • Audio glitching

Severity is high: the defect causes a host bugcheck and loss of unsaved work.
It has occurred three times on this machine.

Link to glitch trace

No Feedback Hub or CollectAudioLogs link is available. This report includes
the WER bugcheck signatures and exact driver/PDB resolution. A minidump can be
shared privately after it is copied from the protected Windows directory.

Steps to reproduce

The user-level trigger is intermittent. These are the conditions under which
the issue has occurred:

  1. Install and activate the repository's experimental USBAudio2-ACX driver
    for a TASCAM Model 12.
  2. Connect the Model 12 through the USB 2.0 hub described above.
  3. Configure the Windows Model 12 playback and capture endpoints for 48 kHz.
  4. Exercise normal shared-mode render/capture stream transitions, including
    opening and closing Guitar Pro and then starting browser playback.
  5. Repeat stream start/stop and application handoff operations.

Observed result: Windows eventually bugchecks with
SYSTEM_THREAD_EXCEPTION_NOT_HANDLED (0x7E), exception 0xC0000094, and the
blue screen names USBAudio2_ACX.sys.

The source-level triggering condition is clearer than the user-level sequence:

  1. m_transferredBytesInThisIrp is zero. This is its initial value, and one
    reachable path leaves it zero when an isochronous IN URB completes with
    successful packets whose total payload is zero bytes.
  2. A render or capture RT packet path calls
    TransferObject::CalculateEstimatedQPCPosition(...).
  3. The function evaluates
    (m_periodQPCPosition * bytesCopiedUpToBoundary) / m_transferredBytesInThisIrp without a zero check.
  4. The kernel raises integer divide-by-zero and bugchecks.

The exact crashing caller, render versus capture, still needs an elevated
minidump stack because the current analysis process could not read the
protected dump.

Expected behavior

Zero-byte transfers and stream startup/shutdown transitions should be handled
without dividing by zero. The driver should preserve a conservative QPC
position or skip packet-progress notification until a non-empty transfer is
available. Windows must not crash.

Additional notes

Repeated crash signature

Windows Event Reporting recorded the same exception and stable driver-relative
instruction on three dates:

Time Bugcheck Exception Fault address Derived image base Driver RVA WER report ID Minidump name
2026-07-09 00:30 0x7E 0xC0000094 0xFFFFF8079C7D6BBC 0xFFFFF8079C780000 0x56BBC 55df788d-9112-41c2-b4bb-af6a59e1aa3c 070926-10218-01.dmp
2026-07-14 13:49 0x7E 0xC0000094 0xFFFFF803851F6BBC 0xFFFFF803851A0000 0x56BBC df1302d7-a1c0-4268-8cea-ea3ae7bf6a3e 071426-14750-01.dmp
2026-07-15 18:13 0x7E 0xC0000094 0xFFFFF80074B56BBC 0xFFFFF80074B00000 0x56BBC 53d16d14-7ded-4703-8ba3-7c2042dfb28b 071526-9750-01.dmp

The image base changed because of ASLR; the fault remained at RVA 0x56BBC.

The latest WER bugcheck parameters were:

0x0000007e
0xffffffffc0000094
0xfffff80074b56bbc
0xffff810f8b6d6de8
0xffff810f8b6d65f0

Installed driver build

  • Device name: USBAudio2-ACX
  • Package: oem100.inf
  • Package version: 11.0.45.967
  • Package driver date: 2026-06-25
  • Installed binary: USBAudio2-ACX.sys
  • Binary size: 496552 bytes
  • Binary SHA-256:
    93F29CCD9A02D93F3144BACB055364EE4CB272454369E53C442A692DE1B95D6C
  • Binary file/product version: 1.0
  • The file has a local WDK test signature. Win32_PnPSignedDriver reports
    IsSigned=False, so this is not a production-signed package.
  • The installed binary exactly matches the staged x64 Release binary in the
    reporter's checkout.
  • Checkout at analysis time:
    7a7f6166b0e816e5d22686cb3675308140b7d4af
  • Upstream main observed at analysis time:
    93fc4b7cce13aeb1bdd2cac7cb0c41c78fff1699

The checkout already includes commit f35e5b0, the fix from the existing
WASAPI-exclusive/WAVEFORMATEXTENSIBLE issue branch. The divide-by-zero code is
unchanged by that fix and appears to be a separate defect.

Symbol and instruction resolution

The exact PDB generated with the installed binary was retained. Resolving
relative address 0x56BBC against that binary/PDB gives:

TransferObject::CalculateEstimatedQPCPosition(unsigned long)
src/uac2-driver/TransferObject.cpp:1418

The instruction at that RVA is:

140056b9b: imulq  0x10c8(%rdi), %rbx
140056ba3: movl   0x7c(%rdi), %ecx
140056baf: movq   %rbx, %rax
140056bb6: xorl   %edx, %edx
140056bbc: divq   %rcx
140056bbf: addq   0x10b8(%rdi), %rax

The denominator is loaded from the transfer object's
m_transferredBytesInThisIrp member immediately before divq.

Faulting source

src/uac2-driver/TransferObject.cpp:1410-1418:

ULONGLONG
TransferObject::CalculateEstimatedQPCPosition(
    ULONG bytesCopiedUpToBoundary
)
{
    PAGED_CODE();
    TraceEvents(TRACE_LEVEL_VERBOSE, TRACE_DEVICE,
        " %llu + (%llu * %u) / %u = %llu",
        m_qpcPosition, m_periodQPCPosition,
        bytesCopiedUpToBoundary, m_transferredBytesInThisIrp,
        m_qpcPosition +
            (m_periodQPCPosition * bytesCopiedUpToBoundary) /
            m_transferredBytesInThisIrp);

    return m_qpcPosition +
        (m_periodQPCPosition * bytesCopiedUpToBoundary) /
        m_transferredBytesInThisIrp;
}

Both the trace argument and return expression divide by the member, so the
guard must be placed before the existing TraceEvents call.

Reachable zero-denominator path

The following current source behavior makes zero a valid runtime state:

  • m_transferredBytesInThisIrp is initialized to zero in
    src/uac2-driver/TransferObject.h.
  • UpdateTransferredBytesInThisIrp() initializes its output count to zero at
    TransferObject.cpp:991.
  • The IN path adds each successful packet's length at lines 1012-1013.
  • A successful zero-length IN packet is explicitly accepted and logged at
    lines 1020-1033 rather than treated as a failed transfer.
  • If every successful packet is zero length, the accumulated count remains
    zero and is stored in m_transferredBytesInThisIrp at line 1111.
  • Render and capture packet processing both call the estimator when
    LastPacketStartQpcPosition == 0 at RtPacketObject.cpp:663 and :883.
  • They also call it for packet-boundary interpolation at
    RtPacketObject.cpp:671 and :890.

Even bytesCopiedUpToBoundary == 0 does not make this safe: 0 / 0 still
raises the integer divide exception.

Suggested correction

Handle an empty transfer before evaluating either division. A conservative
minimal guard is:

if (m_transferredBytesInThisIrp == 0)
{
    TraceEvents(
        TRACE_LEVEL_WARNING,
        TRACE_DEVICE,
        "Cannot interpolate QPC position for an empty transfer");
    return m_qpcPosition;
}

The RT packet paths should also be reviewed to ensure they do not report ACX
packet progress derived from an empty transfer. Returning m_qpcPosition
prevents extrapolation when there is no byte ratio; skipping notification may
be more appropriate depending on the packet-state contract.

Suggested validation

  1. Inject an isochronous IN completion in which all packet statuses are
    successful and all packet lengths are zero.
  2. Exercise the first render and capture packet while
    LastPacketStartQpcPosition == 0.
  3. Exercise a null/not-yet-populated transfer state if that state is legal.
  4. Run repeated render-only, capture-only, and full-duplex stream start/stop
    loops at 48 kHz.
  5. Repeat through both a direct motherboard USB port and the currently used
    USB 2.0 hub.
  6. Repeat shared-mode browser playback and Guitar Pro application handoffs.
  7. Verify that QPC positions remain monotonic and that no packet-complete
    notification is emitted for data that was not transferred.
  8. Confirm no divide-by-zero with tracing enabled, because the current trace
    expression contains the same unsafe division as the return expression.

Dump and attachment status

The latest blue-screen photo is available as bsod-photo.jpg and visibly
shows:

SYSTEM_THREAD_EXCEPTION_NOT_HANDLED (0x7E)
What failed: USBAudio2_ACX.sys

Windows named these minidumps in WER records:

C:\Windows\Minidump\070926-10218-01.dmp
C:\Windows\Minidump\071426-14750-01.dmp
C:\Windows\Minidump\071526-9750-01.dmp

The latest full dump is C:\Windows\MEMORY.DMP, 8,143,200,169 bytes,
timestamped 2026-07-15 18:13:44. Windows also logged volmgr event 161 while
writing it at BugCheckProgress 0x43, so it may be incomplete.

The current analysis process ran at medium integrity. WinDbg could not open
the protected dump and returned Win32 error 5, Access is denied. Therefore a
full !analyze -v stack is not included yet. The function and faulting
instruction were instead resolved from three repeated WER addresses, the
installed image, and its exact matching PDB.

Recommended public attachments:

  • bsod-photo.jpg
  • This report or its crash-signature and technical-analysis sections

Available privately to the driver team:

  • The smallest readable minidump
  • Exact installed USBAudio2-ACX.sys
  • Matching USBAudio2-ACX.pdb
  • Guitar Pro log containing the PortAudio stop-stream failures
  • Full kernel dump if required and if WinDbg confirms it is readable

The full dump and PDB should not be uploaded publicly without review because
they may expose machine memory or local build paths.

Workaround

Removing experimental package oem100.inf and returning the Model 12 to the
available TEAC model2400 driver avoids continued exposure to this known
kernel-crash path. The rollback was not performed during evidence collection,
so the experimental driver was still installed after the latest reboot.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Labels

No labels
No labels

Type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions