2012-07-20 14 views
59

Có một Vi phạm Sonar:Sonar Vi phạm: An ninh - Mảng được lưu trữ trực tiếp

Sonar Vi phạm: An ninh - Mảng được lưu trữ trực tiếp

public void setMyArray(String[] myArray) { 
    this.myArray = myArray; 
} 

Giải pháp:

public void setMyArray(String[] newMyArray) { 
    if(newMyArray == null) { 
    this.myArray = new String[0]; 
    } else { 
    this.myArray = Arrays.copyOf(newMyArray, newMyArray.length); 
    } 
} 

Nhưng tôi tự hỏi tại sao?

+10

Umm ... giải pháp mà không làm việc cho tôi, thực sự. Sonar vẫn nhặt nó lên và phàn nàn về nó, mặc dù làm một bản sao. – ndtreviv

+1

@ndtreviv để bạn giải quyết nó như thế nào? – sakura

+2

@ndtreviv: Tôi đã gặp vấn đề này, và lỗi này sẽ không biến mất nếu tên của biến cục bộ được cung cấp cho phương thức này giống như biến cá thể bạn đang lưu trữ. Đảm bảo chúng khác nhau và giải pháp trên sẽ hoạt động. Tôi tìm thấy điều này thông qua [link] sau đây (http://sonarqube.15.x6.nabble.com/Security-Array-is-stored-directly-weirness-td3632714.html) – Matt

Trả lời

52

Việc khiếu nại mảng mà bạn đang lưu trữ là cùng một mảng do người gọi giữ. Nghĩa là, nếu người gọi sau đó sửa đổi mảng này, mảng được lưu trữ trong đối tượng (và do đó chính đối tượng đó) sẽ thay đổi.

Giải pháp là tạo một bản sao trong đối tượng khi nó được thông qua. Điều này được gọi là sao chép phòng thủ. Một sửa đổi tiếp theo của bộ sưu tập sẽ không ảnh hưởng đến mảng được lưu trữ trong đối tượng.

Thực tiễn tốt là thường làm điều này khi trả lại bộ sưu tập (ví dụ: trong một cuộc gọi getMyArray() tương ứng). Nếu không, người nhận có thể thực hiện một sửa đổi và ảnh hưởng đến thể hiện được lưu trữ.

Lưu ý rằng điều này rõ ràng áp dụng cho tất cả các bộ sưu tập có thể thay đổi (và trên thực tế tất cả các đối tượng có thể thay đổi) - không chỉ là mảng. Cũng lưu ý rằng điều này có tác động hiệu suất cần được đánh giá cùng với các mối quan tâm khác.

+0

Tôi có thể thấy lý do .... những gì nếu tôi cố ý muốn người gọi và mục tiêu của nó giữ cùng một bản sao? –

+2

Đó là một quyết định thiết kế. Nhưng tôi nghĩ rằng điều quan trọng là phải hiểu * ai * sở hữu dữ liệu này và cách (nếu cần) bạn thông báo cho các đối tượng đang giữ nó rằng nó đã thay đổi. Nó khá hợp lý trong tập hợp các thành phần liên quan chặt chẽ đến việc vượt qua các bộ sưu tập xung quanh mà không cần sao chép phòng thủ. Nhưng tại một số điểm, bạn sẽ cần phải bảo vệ bản thân (ví dụ: cắm vào mã thứ ba hoặc mã của khách hàng) –

+1

chắc chắn OP * là * tạo bản sao phòng thủ với 'this.myArray = Arrays.copyOf (newMyArray, newMyArray.length); '? – Qwerky

22

Nó được gọi là sao chép phòng thủ. Một bài viết hay về chủ đề là "Whose object is it, anyway?" bởi Brian Goetz, thảo luận về sự khác biệt giữa giá trị và ngữ nghĩa tham chiếu cho getters và setters. Về cơ bản, rủi ro với ngữ nghĩa tham chiếu (không có bản sao) là bạn giả tưởng rằng bạn sở hữu mảng và khi bạn sửa đổi nó, bạn cũng sửa đổi các cấu trúc khác có bí danh cho mảng đó. Bạn có thể tìm thấy nhiều thông tin về sao chép phòng thủ và các vấn đề liên quan đến bí danh đối tượng trực tuyến.

+0

cảm ơn bạn đời, def a up bỏ phiếu. bạn có thể làm một ví dụ nhỏ, hoặc nén lý do trong 50 từ? –

+1

@ewernli: Liên kết đã bị hỏng, Vui lòng sửa lỗi. Cảm ơn! –

+1

@KugathasanAbimaran Liên kết hoạt động trở lại! – ewernli

12

tôi đã cùng một vấn đề:

An ninh - Mảng được lưu trữ trực tiếp Các người dùng cung cấp mảng 'palomitas' được lưu trữ trực tiếp.

phương pháp ban đầu của tôi:

public void setCheck(boolean[] palomitas) { 
     this.check=palomitas; 
    } 

cố định quay sang:

public void setCheck(boolean[] palomitas) { 
     if(palomitas == null) { 
     this.check = new boolean[0]; 
     } else { 
     this.check = Arrays.copyOf(palomitas, palomitas.length); 
     } 
} 

Ví dụ khác:

An ninh - Mảng được lưu trữ trực tiếp Mảng người dùng cung cấp

private String[] arrString; 

    public ListaJorgeAdapter(String[] stringArg) {  
     arrString = stringArg; 
    } 

Cố định:

public ListaJorgeAdapter(String[] stringArg) { 
    if(stringArg == null) { 
     this.arrString = new String[0]; 
    } else { 
     this.arrString = Arrays.copyOf(stringArg, stringArg.length); 
    } 
} 
2

Để loại bỏ chúng, bạn phải clone Array trước khi lưu trữ/trả lại nó như thể hiện trong việc thực hiện lớp sau, vì vậy không ai có thể sửa đổi hoặc lấy dữ liệu ban đầu của lớp học của bạn nhưng chỉ có một bản sao của chúng.

public byte[] getarrString() { 
    return arrString.clone(); 
} 
/** 
* @param arrStringthe arrString to set 
*/ 
public void arrString(byte[] arrString) { 
    this.arrString= arrString.clone(); 
} 

tôi đã sử dụng nó như thế này và Bây giờ tôi không nhận được bất kỳ sự vi phạm SONAR ...

0

Có một số trường hợp nó là một quyết định thiết kế và không bỏ lỡ. Trong những trường hợp này, bạn cần phải sửa đổi các quy tắc Sonar để loại trừ nó để nó không hiển thị các vấn đề như vậy trong báo cáo.

2

Dễ dàng hơn tất cả điều này. Bạn chỉ cần đổi tên tham số phương thức thành bất kỳ thứ gì khác để tránh vi phạm Sonar.

http://osdir.com/ml/java-sonar-general/2012-01/msg00223.html

public void setInventoryClassId(String[] newInventoryClassId) 
    {     
      if(newInventoryClassId == null) 
      { 
        this.inventoryClassId = new String[0]; 
      } 
      else 
      { 
        this.inventoryClassId = Arrays.copyOf(newInventoryClassId, newInventoryClassId.length); 
      } 

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