2012-02-15 20 views
10

Cppcheck đã phát hiện một vấn đề tiềm ẩn trong một mã như thế này:Làm cách nào để đọc số bằng sscanf?

float a, b, c; 
int count = sscanf(data, "%f,%f,%f", &a, &b, &c); 

Nó nói rằng: "scanf không có giới hạn chiều rộng lĩnh vực có thể sụp đổ với dữ liệu khổng lồ". Làm thế nào là có thể? Có phải đó là một lỗi đã biết trong một số triển khai sscanf? Tôi hiểu rằng các con số có thể tràn (số lượng), nhưng làm thế nào chương trình có thể sụp đổ? Đó có phải là dương tính giả trong cppcheck không?

Tôi đã tìm thấy câu hỏi tương tự: scanf Cppcheck warning, nhưng câu trả lời không hoàn toàn thỏa mãn. Câu trả lời đề cập đến an toàn loại, nhưng đó không phải là vấn đề ở đây.

+0

Hãy thử sscanf_s thay thế. Như scanf bình thường, sscanf không tràn an toàn. – guitarflow

+2

@guitarflow: Vấn đề là tôi không thấy nơi nó có thể tràn. –

+2

@guitarflow Hoặc không. 'sscanf_s' không di động và cũng không thực sự an toàn, bất chấp tên và gợi ý của Microsoft. –

Trả lời

6

Tôi là nhà phát triển Cppcheck.

Có sự cố lạ này. Với "dữ liệu khổng lồ", nó có nghĩa là hàng triệu chữ số.

Nếu bạn sử dụng cờ --verbose thì cppcheck sẽ thực sự viết một mã ví dụ nhỏ thường bị treo trên máy tính Linux.

Dưới đây là một ví dụ mã mà treo với một lỗi segmentation trên máy tính Ubuntu 11.10 của tôi:

#include <stdio.h> 

#define HUGE_SIZE 100000000 

int main() 
{ 
    int i; 
    char *data = new char[HUGE_SIZE]; 
    for (int i = 0; i < HUGE_SIZE; ++i) 
     data[i] = '1'; 
    data[HUGE_SIZE-1] = 0; 
    sscanf(data, "%i", &i); 
    delete [] data; 
    return 0; 
} 

Đối với thông tin của bạn tôi không nhận được một vụ tai nạn khi tôi cố gắng mã ví dụ này trên visual studio.

Tôi đã sử dụng phiên bản g ++ 4.6.1 để biên dịch.

+1

Câu hỏi vẫn còn. Tại sao nó sụp đổ? Tôi không thấy bất kỳ lý do gì khi mã để phân tích cú pháp số có thể giống như sau: 'cho mỗi chữ số trong dữ liệu: kết quả * = 10; kết quả + = chữ số'. Làm thế nào có thể sụp đổ? Tại sao nó không cố định? –

+0

Tôi chủ yếu muốn trả lời "Đó có phải là dương tính giả trong Cppcheck không?". Đó là một vụ tai nạn kỳ lạ vì vậy thật dễ dàng để nghĩ như vậy. Tôi không thể trả lời tại sao nó bị treo. Nó đã là một vấn đề được biết đến và phổ biến trong nhiều năm. Tôi đồng ý rằng với mã của bạn nó không thể sụp đổ vì vậy rõ ràng đó không phải là cách dữ liệu được phân tích cú pháp. –

+0

Vâng, tôi hiểu. Cảm ơn ít nhất cho một câu trả lời một phần. Tôi đã cho bạn +1. –

1

OK, hãy xem xét mã này:

int main(int argc, char *argv[]) { 
    const char* data = "9999999999999999999999999.9999999999999999999999//i put alot more 9's there, this just to get the point through 
    float a; 
    int count = sscanf(data, "%f", &a); 
    printf("%f",a); 
} 

đầu ra của chương trình này là "inf" - không có tai nạn. Và tôi đặt một số lượng lớn 9 ở đó. Vì vậy, tôi nghi ngờ Cppcheck chỉ đơn giản là sai về điều này.

+0

Bạn đã kiểm tra trình biên dịch nào? –

+0

được biên dịch chỉ với g ++. tại sao, bạn có nhận được kết quả khác với trình biên dịch khác không? – WeaselFox

+0

Chưa, nhưng tôi cảm thấy rằng kết luận "CppCheck chỉ đơn giản là sai" có thể hơi sớm khi thử nghiệm trên 1 trình biên dịch. (Tôi chỉ có thể thử nghiệm với VC++ 2005, nơi tôi đang ngồi bây giờ, xin lỗi.) –

4

Lỗi phân đoạn có vẻ là lỗi trong glibc.

Tôi vừa thử nghiệm điều này với một chương trình tương tự, bị treo trong ubuntu 10.04, nhưng hoạt động trong ubuntu 12.04.

Như Daniel Marjamäki cho biết, chương trình của anh ấy bị treo ở 11,10, tôi tin rằng lỗi là được sửa ở giữa.