2010-07-23 26 views
9

PMD có một quy tắc gọi là ArrayIsStoredDirectly trong ruleset Sun An ninh:lý do đằng sau ArrayIsStoredDirectly cai trị của PMD

nhà xây dựng và phương pháp nhận mảng nên sao chép các đối tượng và lưu trữ các bản sao. Điều này ngăn cản những thay đổi trong tương lai từ người dùng ảnh hưởng đến chức năng nội bộ.

Dưới đây là ví dụ của họ:

public class Foo { 
private String [] x; 
    public void foo (String [] param) { 
     // Don't do this, make a copy of the array at least 
     this.x=param; 
    } 
} 

Tôi không nghĩ rằng tôi hoàn toàn hiểu được lý do đằng sau quy tắc này. Có phải vì các giá trị trong mảng được truyền có thể được thay đổi ở một nơi khác không? Có một sự khác biệt giữa việc vượt qua một Bộ sưu tập vs đi qua một mảng liên quan đến điều này?

+0

Không có sự khác biệt về mảng truyền qua Bộ sưu tập. Một sự khác biệt nhỏ trong việc xử lý an toàn các mảng và các bộ sưu tập là với các mảng được phép gọi là .clone(), nhưng bạn không nên tin tưởng phương thức .clone() của một Collection. –

Trả lời

12

Vấn đề là rằng người gọi có thể giữ một bản sao của đối số mảng mà nó thông qua, và sau đó có thể thay đổi nội dung của nó. Nếu đối tượng là an ninh quan trọng và cuộc gọi được thực hiện từ mã không đáng tin cậy, bạn đã có một lỗ hổng bảo mật.

Trong ngữ cảnh này, chuyển một bộ sưu tập và lưu nó mà không cần sao chép nó cũng sẽ là một nguy cơ bảo mật tiềm ẩn. (Tôi không biết nếu có quy tắc PMD để cho bạn biết điều này.)

Trong cả hai trường hợp, cách để giải quyết rủi ro (nếu là thực) là đặt thuộc tính thành bản sao của mảng đối số hoặc bộ sưu tập. Mặt khác, nếu bạn biết rằng người gọi luôn là mã đáng tin cậy, thì bản sao là một sự lãng phí thời gian, và một giải pháp tốt hơn là nói với PMD phải im lặng về phương pháp cụ thể đó.

+0

Cảm ơn. Tôi đã nhầm lẫn rằng PMD đã phàn nàn về việc trực tiếp thiết lập một mảng nhưng không phải về các bộ sưu tập và nghĩ rằng tôi có thể thiếu một số hiểu biết liên quan đến việc xử lý mảng so với các bộ sưu tập. –

+1

Tôi không nghĩ rằng đi qua một bộ sưu tập sẽ là một nguy cơ bảo mật. Bởi vì nếu bạn lo lắng về mã không đáng tin cậy, bạn có thể sử dụng một bộ sưu tập bất biến. Nhưng một mảng thô không thể thay đổi được. – n3utrino

+0

@gabe - Có hai trường hợp bạn cần xem xét. 1) Bạn vượt qua mã xấu một bộ sưu tập và nó sửa đổi nó. 2) Mã xấu chuyển cho bạn bộ sưu tập và sửa đổi nó sau lưng bạn. Vượt qua ** bảo vệ bộ sưu tập ** không thể sửa đổi được so với 1) nhưng không phải 2. (Không có lớp thu thập bất biến trong Java ... chỉ không thể sửa đổi được ... và sự khác biệt là đáng kể.) –

3

Không có sự khác biệt giữa việc truyền tập hợp hoặc mảng: trong cả hai trường hợp, người gửi và người nhận có thể sửa đổi nội dung của cơ sở dữ liệu. Dưới đây là ví dụ:

// ... in some method 
Foo myfoo = new Foo(); 
String[] array = {"One", "Two", "Three"}; 
myfoo.foo(array);  // now the Foo instance gets {"One", "Two", "Three"} 

array[1] = "Changed"; // now the internal field x in myfoo is {"One", "Changed", "Three"} 

Nếu bạn không muốn hành vi này, bạn phải tuân theo quy tắc PMD này, sao chép mảng trong Foo và lưu trữ tham chiếu tới bản sao. Bằng cách này bạn đảm bảo rằng không có lớp nào khác giữ tham chiếu đến mảng nội bộ của bạn (trừ khi chúng ta quên phản ánh trong một lát và trừ khi chúng ta không trả về mảng nội bộ này theo phương thức khác ...)

1

Tôi nghĩ rằng vấn đề chính với mảng là bạn không thể điều khiển acces với nó.

Nhưng với đối tượng bạn ẩn các thành viên đằng sau người định cư nơi bạn có thể kiểm soát nội dung sẽ được đặt. Tôi nghĩ điều tương tự cũng áp dụng cho Bộ sưu tập vì bạn cần gọi add()toArray() trả về một bản sao.

Các vấn đề liên quan