21. 패킹된 비트플래그/필드 언패킹

난이도 중 해설 보기 →

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

결함 코드 · C#
// ============================================================================
// [코드리뷰 문제] C# - 패킹된 비트플래그/필드 언패킹
// ----------------------------------------------------------------------------
// 시나리오 (프로토콜/패킷 · 서버-클라):
//   - 액션 패킷의 헤더는 여러 필드를 하나의 16비트 정수에 비트로 패킹한다.
//     와이어 포맷(2바이트, 빅엔디안):
//       bit 0..2  : actionType  (0..7)
//       bit 3..6  : slotIndex    (0..15)   ← 장비 슬롯 인덱스
//       bit 7     : urgent       (0/1)
//       bit 8..15 : reserved     (반드시 0)
//   - 서버는 이 2바이트를 받아 각 필드를 언패킹하고, slotIndex 로 장비 배열에 접근한다.
//
// 요구사항:
//   - 각 필드는 정의된 비트 폭/범위 안에서만 해석돼야 한다(slotIndex 는 0..15).
//   - reserved 비트가 0이 아니면(=정의되지 않은 비트) 패킷을 거부해야 한다.
//   - "서버가 신뢰한 요청"임을 나타내는 권한성 표식은 클라가 보낸 값으로 정해선 안 된다
//     (서버 권위). 클라 패킷의 어떤 비트도 검증을 건너뛰게 만들 수 없어야 한다.
//
// 과제:
//   이 디코더/적용 코드의 잠재적 문제를 모두 찾고, 악의적/비정상 입력에서 어떤 일이
//   벌어지는지 설명하고, 수정안과 더 나은 설계를 제시하라.
//   (먼저 직접 리뷰를 적은 뒤 answer.md 와 대조할 것)
// ============================================================================

using System;

public class ActionPacket
{
    public int  ActionType;
    public int  SlotIndex;
    public bool Urgent;
    public bool ServerTrusted;   // 내부 신뢰 표식
}

public class ActionDecoder
{
    private readonly string[] _equip = new string[16];   // 슬롯 0..15

    public ActionPacket Decode(byte[] buf, int offset)
    {
        short packed = (short)((buf[offset] << 8) | buf[offset + 1]);   // (A)

        var p = new ActionPacket();
        p.ActionType    = packed & 0x7;
        p.SlotIndex     = (packed >> 3) & 0x1F;        // (B)
        p.Urgent        = ((packed >> 7) & 1) != 0;
        p.ServerTrusted = ((packed >> 8) & 1) != 0;    // (C)
        return p;
    }

    public void Apply(ActionPacket p)
    {
        if (!p.ServerTrusted)
        {
            if (p.SlotIndex < 0 || p.SlotIndex >= _equip.Length) return;
        }
        var name = _equip[p.SlotIndex];                // (D)
        // ... actionType 에 따라 name 슬롯에 액션 적용
        _ = name;
    }
}
내 리뷰 · C#
내 답안 · 자동 저장

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