23. 배치 메시지 디코딩과 길이/개수 검증 (OOB / 메모리 증폭 / 부분 프레임)

난이도 중 해설 보기 →

결함을 모두 찾고 원인·수정안·더 나은 설계를 제시하라. 마커 (A)(B) 는 주목 위치 힌트다.

결함 코드 · C#
// ============================================================================
// [코드리뷰 문제] C# - 배치(batch) 메시지 디코딩과 길이/개수 검증
// ----------------------------------------------------------------------------
// 시나리오 (프로토콜/직렬화 · 서버-서버):
//   - 존 서버가 한 틱에 모인 여러 논리 메시지를 한 프레임으로 묶어 게이트웨이로 보낸다.
//   - 와이어 포맷(리틀엔디안):
//       [u16 count] 그 다음 count 개의 항목, 각 항목 = [u16 type][u16 len][len 바이트 payload]
//   - 수신 측은 한 프레임(buf)을 받아 항목들로 풀어 처리 큐에 넣는다.
//   - buf 는 네트워크에서 온 신뢰할 수 없는 바이트이며, 길이도 다양하다.
//
// 과제:
//   이 코드의 잠재적 문제를 모두 찾고, 손상되거나 악의적으로 조작된 프레임(예: 큰 count,
//   실제 남은 바이트보다 큰 len)이 들어왔을 때 무슨 일이 일어나는지 설명하라. 또 프레임이
//   덜 도착한 경우(부분 수신)의 동작도 함께 논하라. 수정안과 더 나은 설계를 제시하라.
//   (먼저 직접 리뷰를 적은 뒤 answer.md 와 대조할 것)
// ============================================================================

using System;
using System.Collections.Generic;

public struct Msg
{
    public ushort Type;
    public byte[] Payload;
}

public class BatchDecoder
{
    public List<Msg> Decode(byte[] buf)
    {
        var list = new List<Msg>();
        int off = 0;

        ushort count = ReadU16(buf, ref off);          // (A) 항목 개수
        for (int i = 0; i < count; i++)
        {
            ushort type = ReadU16(buf, ref off);       // (B) 타입
            ushort len  = ReadU16(buf, ref off);       // (C) 항목 길이

            var payload = new byte[len];               // (D) 길이만큼 선할당
            Array.Copy(buf, off, payload, 0, len);     // (E) 페이로드 복사
            off += len;

            list.Add(new Msg { Type = type, Payload = payload });
        }
        return list;
    }

    private static ushort ReadU16(byte[] b, ref int o)  // (F) 경계 확인 없음
    {
        ushort v = (ushort)(b[o] | (b[o + 1] << 8));
        o += 2;
        return v;
    }
}
내 리뷰 · C#
내 답안 · 자동 저장

작성 후 위 해설 보기에서 모범 해설과 대조하세요.