Auto-generate catch-and-default-reply wrappers for Swift IPC receivers
Component: WebKit IPC Infrastructure | 6055228
WebKit의 UIProcess, Networking, GPU process는 sandbox 안에서 동작하는 WebContent process로부터 IPC 메시지를 받습니다. 보내는 쪽은 이미 장악되었을 가능성이 있는 프로세스인 만큼, handler 코드가 실행되기 전에 messageCheck가 메시지 인자를 검증합니다. 문제는 reply를 기대하는 메시지입니다. 검증에 실패하더라도 어떤 값이든 반드시 회신해야 하고, 그렇지 않으면 sender 쪽이 영원히 block됩니다. 그래서 Swift receiver마다 실패 경로에서 사용할 기본 reply 값을 손으로 작성해 왔습니다. 이때 reply의 Swift signature와 그 자리를 대신하는 fallback 값이 조용히 어긋나는 상황이 가능했습니다.
이번 commit은 Swift 기반 receiver 전체에 대해, 이 catch 처리와 기본 reply 로직을 .messages.in schema로부터 직접 생성하도록 했습니다. 생성된 wrapper는 receiver의 WeakRef 클래스에 자리잡으며, IPC::Connection을 일관된 형태로 받습니다. reply를 기대하는 메시지에서 messageCheck 검증이 실패하면, 함께 생성된 completeWithDefaultReply()가 호출됩니다. 한편 handleMessageAsync의 connection 인자 전달 방식도 handleMessage 및 handleMessageSynchronous와 동일한 형태로 정리되었습니다.
Significance
손으로 작성한 기본 reply는 그것이 대신하는 reply signature와 어긋날 수 있습니다. 같은 .messages.in schema에서 생성하면 이런 어긋남이 구조적으로 사라집니다. IPC handler의 메시지 검증은 sandbox 경계를 지키는 security control에 해당합니다. 그리고 그 control의 실패 경로야말로 테스트가 가장 닿지 않는 코드입니다.
Audit directions
여기서 가져갈 패턴은, security control의 실패 경로를 호출 지점마다 손으로 작성해 둔 구조입니다. 좁은 범위: handleMessageAsync의 connection 인자 전달 방식이 이제 나머지 두 dispatch 경로와 일치합니다. 그러면 connection을 다른 방식으로 넘기는 receiver가 남아 있을 경우 그쪽이 예외적인 사례에 해당하므로, 전부 찾아 목록으로 정리해 볼 만합니다. 더 넓은 범위: C++ IPC receiver도 검증 실패 시 회신해야 할 의무는 동일하지만, 이번 codegen 작업의 대상은 아니었습니다. 해당 쪽에 손으로 작성된 기본 reply가 reply signature와 어긋나 있지 않은지 점검할 필요가 있고, 아무 회신 없이 return해 버리는 실패 경로가 있는지도 함께 확인해야 합니다. 가장 넓은 범위: 성공과 실패 양쪽 모두에서 응답이 필요한 protocol이라면, 실패 쪽 branch야말로 뒤를 받쳐주는 integration test가 없는 경로입니다. 성공 branch를 정의하는 것과 동일한 schema에서 실패 branch까지 생성하는 방식이 일반적인 해법입니다. 코드 리뷰에서의 단서: 검증 실패 branch 안에 리터럴 기본값이 박혀 있고, 그 바로 옆에 타입이 다른 곳에 선언된 reply completion handler가 놓여 있는 경우입니다.