🪝 외부 참조를 Private 필드에 저장 KISA A-6 · 호출자 배열 참조 저장

생성자/세터가 호출자의 배열 참조를 private 필드에 그대로 저장합니다. 호출자는 같은 참조를 들고 있다가 나중에 변조하고, 메서드 호출 없이도 객체의 내부 상태가 그 아래에서 함께 바뀝니다.

① 생성자가 호출자 배열을 그대로 저장 VULNERABLE

new Order(items)는 this.items = items;로 호출자 배열을 앨리어싱합니다. 호출자는 여전히 살아있는 참조를 들고 있어, 생성 후에도 주문 내용을 마음대로 수정할 수 있습니다.

외부 배열 (호출자 소유)

—

Order 내부 상태 (private)

—

② 생성자가 방어적 복사본을 저장 SECURE

수정본은 입력 시 this.items = Arrays.copyOf(input, input.length);로 복사합니다. 객체가 자신만의 배열을 소유하므로, 이후 호출자 배열을 변조해도 내부에 닿지 못합니다.

외부 배열 (호출자 소유)

—

Order 내부 상태 (private)

—

③ 취약 vs 안전 코드

VULNERABLE
// Java
public class Order {
  private String[] items;

  public Order(String[] items) {
    this.items = items;            // ⚠ stores caller's ref
  }
  public void setItems(String[] items) {
    this.items = items;            // ⚠ same problem
  }
  public String[] view(){ return items.clone(); }
}

// caller keeps the reference and edits it later:
String[] cart = {"apple:1"};
Order o = new Order(cart);
cart[0] = "apple:-9999";           // order changed!
cart = append(cart, "LAPTOP:0");   // (re-set) injects item
SECURE
// Java — defensive copy on input
public class Order {
  private final String[] items;

  public Order(String[] items) {
    // copy so we don't alias the caller's array
    this.items = Arrays.copyOf(items, items.length);
  }
  public void setItems(String[] items) {
    this.items = Arrays.copyOf(items, items.length);
  }
  public String[] view(){ return items.clone(); }
}

// caller's later edits hit only their own array:
String[] cart = {"apple:1"};
Order o = new Order(cart);
cart[0] = "apple:-9999";           // order UNCHANGED
대칭 팁: 이것은 "private 배열 반환"의 입력 측 쌍둥이입니다. 둘 다 앨리어싱 버그이며 — 들어올 때(생성자/세터)와 나갈 때(게터) 모두 복사해야 합니다. 방어 핵심: 저장하는 입력에 Arrays.copyOf/clone() · 불변 컬렉션(List.copyOf)과 final 필드 선호 · 원본이 아닌 복사본을 검증(TOCTOU 안전) · 중첩 가변 객체는 깊은 복사.
⚠️ 교육용 시뮬레이션입니다. 객체·private 필드·호출자는 모두 Java 동작을 모사한 페이지 내부 JavaScript mock이며 실제 시스템은 없습니다.