简体   繁体   English

分段错误增加地图

[英]Segmentation fault incrementing a map

I am trying to trace/fix a segmentation fault in my program. 我正在尝试跟踪/修复程序中的分段错误。 My program works fine when perform() has only one iteration of "protos", but not with two. 当perform()仅具有一次“ protos”迭代但没有两次迭代时,我的程序运行良好。 On the second, I get a segmentation fault after the first iteration. 在第二个上,第一次迭代后出现了分割错误。 I am pretty sure that the way I am dealing with iterating and deleting elements in my map in write_blacklist() is correct, but it still reports that it is the error. 我非常确定我在write_blacklist()中迭代和删除映射中元素的方式是正确的,但是它仍然报告这是错误。 I thought that it may be because the map is empty, but I did checks to avoid that and it still throws a segmentation fault. 我以为可能是因为地图是空的,但是我做了检查来避免这种情况,并且仍然抛出了分割错误。

For write_blacklist(), all it should just safely do its iterations and delete the map elements that meet the conditions. 对于write_blacklist(),所有操作都应该安全地进行迭代并删除符合条件的map元素。

(gdb) run
Starting program: /root/BruteBlock/a.out 
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib64/libthread_db.so.1".
openssh
vsftpd
115.239.198.235 already in blacklist, skipping...
121.14.7.244 already in blacklist, skipping...
42.7.26.88 already in blacklist, skipping...
143.137.151.22 already in blacklist, skipping...
58.87.67.58 already in blacklist, skipping...
60.173.82.156 already in blacklist, skipping...
[New Thread 0x7ffff2d34700 (LWP 2087)]
[Thread 0x7ffff2d34700 (LWP 2087) exited]
[New Thread 0x7ffff2d34700 (LWP 2088)]
[Thread 0x7ffff2d34700 (LWP 2088) exited]
[New Thread 0x7ffff2d34700 (LWP 2089)]
[Thread 0x7ffff2d34700 (LWP 2089) exited]
Detaching after fork from child process 2090.
115.239.198.235 already in iptables, skipping...
121.14.7.244 already in iptables, skipping...
42.7.26.88 already in iptables, skipping...
143.137.151.22 already in iptables, skipping...
58.87.67.58 already in iptables, skipping...
60.173.82.156 already in iptables, skipping...
[New Thread 0x7ffff2d34700 (LWP 2091)]
[Thread 0x7ffff2d34700 (LWP 2091) exited]

Program received signal SIGSEGV, Segmentation fault.
0x000000000040c1e6 in std::__detail::_Hash_node<std::pair<std::string const, int>, true>::_M_next (this=0x0)
    at /opt/rh/devtoolset-7/root/usr/include/c++/7/bits/hashtable_policy.h:285
285       { return static_cast<_Hash_node*>(this->_M_nxt); }
Missing separate debuginfos, use: debuginfo-install cyrus-sasl-lib-2.1.26-21.el7.x86_64 glibc-2.17-196.el7_4.2.x86_64 keyutils-libs-1.5.8-3.el7.x86_64 krb5-libs-1.15.1-8.el7.x86_64 libcom_err-1.42.9-10.el7.x86_64 libcurl-7.29.0-42.el7_4.1.x86_64 libgcc-4.8.5-16.el7_4.1.x86_64 libidn-1.28-4.el7.x86_64 libselinux-2.5-11.el7.x86_64 libssh2-1.4.3-10.el7_2.1.x86_64 libstdc++-4.8.5-16.el7_4.1.x86_64 nspr-4.13.1-1.0.el7_3.x86_64 nss-3.28.4-15.el7_4.x86_64 nss-pem-1.0.3-4.el7.x86_64 nss-softokn-3.28.3-8.el7_4.x86_64 nss-softokn-freebl-3.28.3-8.el7_4.x86_64 nss-sysinit-3.28.4-15.el7_4.x86_64 nss-util-3.28.4-3.el7.x86_64 openldap-2.4.44-5.el7.x86_64 openssl-libs-1.0.2k-8.el7.x86_64 pcre-8.32-17.el7.x86_64 sqlite-3.7.17-8.el7.x86_64 zlib-1.2.7-17.el7.x86_64
(gdb) bt
#0  0x000000000040c1e6 in std::__detail::_Hash_node<std::pair<std::string const, int>, true>::_M_next (this=0x0)
    at /opt/rh/devtoolset-7/root/usr/include/c++/7/bits/hashtable_policy.h:285
#1  0x000000000040a829 in std::__detail::_Node_iterator_base<std::pair<std::string const, int>, true>::_M_incr (
    this=0x7fffffffde20) at /opt/rh/devtoolset-7/root/usr/include/c++/7/bits/hashtable_policy.h:314
#2  0x0000000000409612 in std::__detail::_Node_iterator<std::pair<std::string const, int>, false, true>::operator++ (
    this=0x7fffffffde20) at /opt/rh/devtoolset-7/root/usr/include/c++/7/bits/hashtable_policy.h:369
Python Exception <class 'gdb.error'> There is no member or method named _M_bbegin.: 
#3  0x000000000040597e in BruteBlock::write_blacklist (this=0x7fffffffe130, ips=std::unordered_map with 0 elements, 
    output_file="/etc/blacklist.lst") at BruteBlock.cpp:68
#4  0x0000000000406552 in BruteBlock::perform (this=0x7fffffffe130) at BruteBlock.cpp:188
#5  0x0000000000404e8c in main () at main.cpp:18

main.cpp: main.cpp:

while (true) {
18: b.perform();
    sleep(b.get_interval());
}

BruteBlock.cpp::perform(): BruteBlock.cpp :: perform():

void BruteBlock::perform() {
    // Hopefully this will become more elegant!
    for (auto i : protos) {
        std::unordered_map<std::string, int> r(retr_fails(i.logfile, i.expr));
        if (r.empty()) {
        } else {
            write_blacklist(r, blacklist_);
188:        block(blacklist_);
        }
    }
}

BruteBlock.cpp::write_blacklist(): BruteBlock.cpp :: write_blacklist():

void BruteBlock::write_blacklist(std::unordered_map<std::string, int> &ips, const std::string &output_file) {
    std::ifstream is(output_file.c_str());

    if (!is) throw std::runtime_error("Error opening blacklist");
    if (ips.empty()) return;

    // ignore duplicates
    std::string buf;
    while (std::getline(is, buf)) {
        if (ips.find(buf) != ips.end()) {
            ips.erase(buf);
            std::cout << buf << " already in blacklist, skipping..." << '\n';
        }
    }

    // delete the IPs that don't meet the criteria
    auto a = ips.begin();
    while (a != ips.end()) {
        if (a->second < max_attempts_) {
            a = ips.erase(a);
        } else {
            if (a->second > max_attempts_) {
                if (check_reports(a->first) < max_reports_) {
                    a = ips.erase(a);
                }
            }
68:         ++a;
        }
    }

    // write the remaining IPs to the blacklist
    std::ofstream os(output_file.c_str(), std::ios_base::app);

    if (!os) throw std::invalid_argument("Error opening blacklist file");

    for (auto f : ips) {
        if ((f.second > max_attempts_) && (check_reports(f.first) > max_reports_)) {
            os << f.first << '\n';
            std::cout << f.first << " had " << f.second << " failed attempts and " << check_reports(f.first)
                      << " abuse reports, adding to blacklist...\n";
        }
    }

}

In your last loop, j3 lines above the line you've labeled with 68: , you have a = ips.erase(a); 在您的最后一个循环中,在您用68:标记的行上方的j3行,您有a = ips.erase(a); . If you're erasing the last node in the map, a will point to ips.end() after that erase. 如果您要删除地图中的最后一个节点,则在擦除之后a将指向ips.end() When you attempt to increment a on line 68 you get the segmentation fault since you can't increment an iterator the end iterator. 当您尝试增加a在线68你得到的分段错误,因为你不能增加一个迭代的end迭代器。

The solution would be to not increment a if you're erasing it. 解决的办法是在擦除时不增加a

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM