← All issues

[20] [JSC] DFG object allocation sinking shouldn't insert a check when given a PutByVal

Severity: Medium | Component: JSC DFG JIT | cdfa73f

DFG allocation sinking 단계에 잔존하던 특수 처리 코드가 현재 graph invariant를 위반하는 IR을 생성했기 때문에 Medium으로 분류되었습니다. --validateGraph 빌드에서는 GetButterfly validator rule 위반이 발생했습니다. Release 빌드에서는 잘못 컴파일된 graph가 이후 단계에 전달되어 일관성 없는 exit-state metadata를 동반할 가능성이 있습니다.

ObjectAllocationSinkingPhase::run() 안에 남아 있던 if (node->op() == PutByVal) 블록이 합성된 PutHint 앞에 저장 값에 대한 Check를 삽입했습니다. 이 블록은 현재 교체된 array-sinking 구현을 위한 수정 코드였으며, 주변 코드의 invariant와 더 이상 일치하지 않았습니다.

Source/JavaScriptCore/dfg/DFGObjectAllocationSinkingPhase.cpp / DFGValidate.cpp

- if (node->op() == PutByVal) {
- Edge value = m_graph.varArgChild(node, 2);
- m_insertionSet.insertNode(nodeIndex + 1, SpecNone, Check, node->origin, Edge(value.node(), value.useKind()));
- }
- case GetButterfly:
- VALIDATE((node), !node->child1()->isPhantomAllocation());
- break;

주변 알고리즘이 교체된 이후에도 잔존하여, 현재 DFG graph invariant를 위반하는 node를 생성하던 최적화 단계의 오래된 code path.

GetButterfly validator rule도 함께 제거되었습니다. 이는 allocation-sinking 처리 과정이 이제 이전 validator에서 금지했던 형태를 합법적으로 생성하게 되었음을 나타냅니다.

회귀 테스트는 --validateGraphAtEachPhase=1 --validateGraph=true 옵션 하에서 단순한 array-store loop를 실행합니다. 이는 fuzzer minimization 또는 내부 validation 기반 crash에서 비롯된 패턴으로 볼 수 있습니다. Apple은 commit의 rdar/backport metadata를 근거로 이 수정을 보안 관련 사항으로 분류했습니다. 다만 diff 자체는 해당 단계가 validator에서 금지된 graph 형태를 생성했음을 드러낼 뿐이며, release 빌드에서 나타나는 downstream 결과는 diff만으로는 드러나지 않습니다.

이 vulnerability는 renderer 내부에서 DFG compiler의 correctness 보장을 약화시킵니다. 패치 이전에는 해당 단계가 DFG validation invariant를 위반하는 graph를 생성할 수 있었습니다. 결과적으로 이후 단계들이 일관성 없는 IR을 기반으로 동작하게 될 가능성이 있었습니다.