2008-10-03 25 views
16

Tôi đã được yêu cầu duy trì một mật mã C++ lớn đầy lỗ rò bộ nhớ. Trong khi chọc quanh, tôi phát hiện ra rằng chúng tôi có rất nhiều tràn bộ đệm dẫn đến rò rỉ (làm thế nào nó đã xấu này, tôi không bao giờ muốn biết).Chức năng C/C++ nào thường được sử dụng không chính xác và có thể dẫn đến tràn bộ đệm?

Tôi đã quyết định xóa phần bộ đệm trước, bắt đầu bằng các chức năng nguy hiểm. Các hàm C/C++ nào thường được sử dụng không chính xác và có thể dẫn đến tràn bộ đệm?

Đối với trình biên dịch và/hoặc các công cụ sử dụng để giúp tìm kiếm tràn bộ đệm, tôi đã created another question that deals with this

+0

Tôi không hiểu ý nghĩa của câu hỏi này. Không có hàm nào ở đây gây ra bất kỳ tràn nào nếu được xử lý cẩn thận. – unexist

+2

@unexist: Không có chức năng nào bị lỗi nếu sử dụng đúng cách. Các câu hỏi là những chức năng thường được sử dụng không chính xác và dẫn đến như vậy có thể dẫn đến tràn bộ đệm. –

+0

Trình biên dịch/nền tảng nào bạn đang sử dụng? Có rất nhiều công cụ để tìm kiếm loại điều này một cách tự động. – twk

Trả lời

2

Dưới đây là một số chức năng mà tôi phát hiện ra rằng nguy hiểm:

  • được() - Nó không kiểm tra độ dài của biến và có thể ghi đè lên bộ nhớ nếu đầu vào lớn hơn bộ đệm của biến.
  • scanf() - Tôi rất vui vì Visual Studio đã nói với tôi chức năng này không còn được dùng nữa. Đây là một sửa chữa dễ dàng.
  • strcpy() - Nếu không gian bộ nhớ của nguồn lớn hơn điểm đến, dữ liệu sau khi đích sẽ bị ghi đè.
2

Các liên kết sau đây sẽ cho bạn một cái nhìn toàn diện về các chức năng an ninh trong C++ (shortcut này nằm sau cố định với '_s' để khắc phục các vấn đề như tràn): http://msdn.microsoft.com/en-us/library/8ef0s5kh(VS.80).aspx

EDIT: Liên kết này chứa các chức năng cụ thể mà đã được thay thế: http://msdn.microsoft.com/en-us/library/wd3wzwts(VS.80).aspx

EDIT: tôi nên đề cập đây là những phương pháp của Microsoft, nhưng liên kết vẫn còn hữu ích cho việc xác định chức năng mà được coi là một lá cờ đỏ.

+0

Tuy nhiên, đây là những chức năng không dành cho Windows cụ thể. –

+0

Có, nhưng chúng xác định các chức năng là một vấn đề. –

2

Rất tiếc, mọi mảng có thể gây ra một lỗi tràn bộ đệm:

uint32_t foo[3]; 
foo[3] = WALKED_OFF_END_OF_ARRAY; 

Về mặt chức năng, sprintf sẽ vui vẻ đi ra khỏi cuối của bộ đệm. Nó có thể được thay thế bằng snprintf.

11

Nói chung, mọi chức năng không kiểm tra giới hạn trong đối số. Một danh sách sẽ là

  • được()
  • scanf()
  • strcpy()
  • strcat()

Bạn nên sử dụng kích thước phiên bản hạn chế như stncpy, strncat, fgets, vv Sau đó, hãy cẩn thận trong khi đưa ra giới hạn kích thước; đi vào xem xét các '\ 0' chấm dứt chuỗi.

Ngoài ra, mảng KHÔNG bị ràng buộc kiểm tra trong C hoặc C++. Ví dụ sau sẽ gây ra lỗi.Xem off by one error

int foo[3]; 
foo[3] = WALKED_OFF_END_OF_ARRAY; 

chỉnh sửa: Sao chép câu trả lời của @MrValdez, @Denton Gentry

+1

Tôi không đồng ý: các chức năng kiểm tra giới hạn trong các đối số vẫn còn nguy hiểm. Nếu bạn có thể tràn ngập với strcpy, bạn có thể tràn ngập với strncpy bằng cách nhận được ràng buộc sai, (ví dụ như tăng con trỏ và quên để giảm các ràng buộc). Để tự bảo vệ mình, hãy sử dụng std :: string hoặc tương đương với chuỗi lib. –

+0

Tóm tắt ngắn hơn có thể là "các hàm C có nguy cơ bị tràn. Các hàm C++ thường không" – Aaron

+5

Khi sử dụng các phiên bản strnxxx, hãy cẩn thận rằng chúng có thể tạo ra một chuỗi không bị chấm dứt – Arkadiy

0

Về cơ bản, bất cứ điều gì mà chấp nhận một con trỏ và viết cho nó, mà không kiểm tra độ dài. Vì vậy, giống như strcpy(), sprintf(), v.v.

2

Memcpy() là một loại nguy hiểm khác.

Bất kỳ vòng lặp nào truy cập vào mảng đều là một điểm nguy hiểm, vì không có điểm dừng nào vượt ra ngoài phần cuối mảng.

Bộ nhớ Rò rỉ gây ra do cấp phát bộ nhớ và không giải phóng bộ nhớ. Constructor và destructors nên là một điểm đánh giá mạnh, thứ hai để đảm bảo rằng bất kỳ bộ nhớ được cấp phát nào được giải phóng.

+0

memcpy không nguy hiểm, vì nó chấp nhận một tham số chiều dài, miễn là bộ đệm đích được đồng bộ với độ dài (cả hai đều nằm dưới sự kiểm soát của nhà phát triển), nó không quan trọng nếu bộ đệm nguồn bị xâm phạm. –

2

Bạn đang sử dụng phiên bản studio trực quan nào? Trong năm 2008 với tất cả các cảnh báo được kích hoạt, tất cả các chức năng bạn đề cập (và nhiều hơn nữa) cảnh báo bạn rằng chúng không được chấp nhận.

Có lẽ bạn có thể kiểm tra xem tất cả cảnh báo đã được bật chưa và để trình biên dịch thực hiện công việc khó khăn cho bạn?

Là một lưu ý phụ, công cụ tuyệt vời writing secure code thực hiện một công việc tuyệt vời giải thích những cạm bẫy khác nhau của một số chức năng cũ hơn.

+0

Tôi đã mở một câu hỏi khác (http://stackoverflow.com/questions/167199/what-cc-tools-can-check-for-buffer-overflows) đề cập đến các công cụ giúp tôi tìm kiếm các hàm có thể tạo tràn . – MrValdez

2

Tôi có cùng một vấn đề trên cơ sở mã mà tôi làm việc. Lời khuyên của tôi: hãy cảnh giác với bất kỳ hàm C nào giống như str *() và mem *(). Cũng phải cảnh giác với bất cứ điều gì mà có một con trỏ đến một bộ đệm, mà không có một chiều dài. Vì nó có vẻ như bạn có cơ hội sử dụng C++ tôi sẽ trong các trường hợp nghiêm trọng nhất cố gắng sử dụng C + + container cho những thứ: vector, chuỗi, bản đồ, vv Những điều này làm cho cuộc sống của bạn dễ dàng hơn nhiều.

Ngoài ra, các công cụ phát hiện sự cố tự động rất tuyệt vời. Nếu bạn có thể sử dụng valgrind tôi muốn giới thiệu nó. Cũng hợp lý Purify là cực kỳ mạnh mẽ, mặc dù không phải rẻ.

3

Câu hỏi bắt đầu vào cuối sai, tôi sợ. Đó là giả định rằng tràn bộ đệm xảy ra trong các chức năng khác. Nguyên nhân phổ biến nhất là toán tử ++, theo kinh nghiệm của tôi, hoặc cách khác là thiếu toán tử! =.

Giải pháp tốt nhất để tìm lô là/GS trong Visual Studio 2005/8. Nó sẽ không tìm thấy tất cả chúng, nhưng đó là một cách rẻ tiền để giảm số lượng công việc thủ công cần thiết.

5

Valgrind là người bạn thân nhất của bạn.

valgrind --tool = memcheck --leak kiểm tra = đầy đủ ./a.out

1

Một Gotcha bổ sung trong C là "strncpy()" chức năng. Nhiều người không nhận ra rằng nó là miễn phí để trả về một chuỗi mà không phải là null chấm dứt.

+0

+1 [Tại sao 'strncpy' không an toàn?] (Http://stackoverflow.com/questions/869883/why-is-strncpy-insecure). Ngoài ra, ['strtok' là chuỗi không an toàn] (http://stackoverflow.com/questions/5999418/why-is-strtok-considered-unsafe) và rủi ro quá. – legends2k

+0

http://stackoverflow.com/questions/869883/why-is-strncpy-insecure – jdkoftinoff

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