Comment 3 for bug 1541152

Revision history for this message
Christian Ehrhardt  (paelzer) wrote :

The error still exists in the latest versions.

Here a bit of extra info:
I rebuilt the crash data and added package info.
$ sudo apport-retrace /var/crash/_usr_bin_python2.7.0.crash --rebuild-package-info --sandbox system

These c libraries into pytohn bindings are annoying to debug.
But I see it clearly crashes in /usr/lib/python2.7/dist-packages/netsnmp/client_intf.x86_64-linux-gnu.so

#0 0x00007f7e03f34120 in ?? () from /usr/lib/python2.7/dist-packages/netsnmp/client_intf.x86_64-linux-gnu.so
No symbol table info available.
#1 0x0000558e7bece43a in PyEval_EvalFrameEx ()
No symbol table info available.
#2 0x0000558e7bed30e2 in PyEval_EvalFrameEx ()
No symbol table info available.
#3 0x0000558e7becb7da in PyEval_EvalCodeEx ()

I'm already sure the implementation is in netsnmp_get of file python/netsnmp/client_intf.c
But I was not able to find a debug info for this lib.
I built the library locally to skip the stripping of debug symbols.
And it already looks better:

#0 netsnmp_get (self=<optimized out>, args=<optimized out>) at netsnmp/client_intf.c:1499
        varlist_iter = 0x0
        session = 0x7ff1e0b19f50
        varlist = 0x7ff1e0a79050
        varbind = <optimized out>
        val_tuple = 0x0
        varlist_len = <optimized out>
        varlist_ind = <optimized out>
        ss = 0x5624d753c6c0
        pdu = 0x5624d753de00
        response = 0x0
        vars = <optimized out>
        tp = <optimized out>
        len = <optimized out>
        oid_arr = 0x5624d753d9f0
        oid_arr_len = 128
        type = <optimized out>
        type_str = "\326\301b\312\326\301b\312\326\301b\312\326\301b\312", '\000' <repeats 15 times>
        str_buf = '\000' <repeats 48 times>, "\a\000@\000\036\000\035\000\344-\245\340\361\177", '\000' <repeats 11 times>, "\200\305\340\361\177\000\000\001\000\000\000\000\000\000\000\217\275\244\340\361\177\000\000\360\204\305\340\361\177\000\000\000\000 \000\000\000\000\000\001\000\000\000\006\000\000\000X\365D\340\361\177\000\000VNr\000\000\000\000\000X\347=\336\361\177\000\000\002", '\000' <repeats 175 times>...
        str_bufp = 0x7ffcf1cdc930 ""
        str_buf_len = 4096
        out_len = 0
        buf_over = 0
        tag = 0x0
        iid = 0x0
        getlabel_flag = 0
        sprintval_flag = 0
        verbose = 1
        old_format = <optimized out>
        best_guess = 0
        retry_nosuch = 0
        err_ind = 1515870810
        err_num = 1515870810
        err_str = "\000\000\000\000\000\000\000\000\350\260\377\324$V\000\000\002", '\000' <repeats 15 times>, "@ޱ\340\361\177", '\000' <repeats 18 times>, "\023\r\003\325$V\000\000\002\000\000\000\000\000\000\000\000\062\271\375\214\272\323?\000\000\000\000\000\000\000\000(ѱ\340\361\177\000\000\377\377\377\377\377\377\377\377\370\377\377\377\377\377\377\377\360\342B\327$V\000\000\360\342B\327$V\000\000\000\000\000\000\000\000\000\000%\322\376\324$V\000\000\020\t\262\340\361\177\000\000\360\t\262\340\361\177\000\000\020\t\262\340\361\177\000\000\360\342B\327$V\000\000\000\000\000\000\000\000\000\000\v\260\377\324$V\000\000@r\377\324$V\000\000\000\000\000\000\000\000\000\000"...
        tmpstr = 0x7ff1e0c1952c ""
        tmplen = 0
#1 0x00005624d500e43a in PyEval_EvalFrameEx ()
No symbol table info available.
#2 0x00005624d50130e2 in PyEval_EvalFrameEx ()
No symbol table info available.
#3 0x00005624d500b7da in PyEval_EvalCodeEx ()
No symbol table info available.
#4 0x00005624d503c72f in ?? ()
No symbol table info available.
#5 0x00005624d4f9a46c in PyRun_InteractiveOneFlags ()
No symbol table info available.
#6 0x00005624d4f9a2b8 in PyRun_InteractiveLoopFlags ()
No symbol table info available.
#7 0x00005624d4f7ff7e in ?? ()
No symbol table info available.
#8 0x00005624d4fe54f4 in Py_Main ()
No symbol table info available.
#9 0x00007ff1e045f00a in __libc_start_main (main=0x5624d4fe4ed0 <main>, argc=1, argv=0x7ffcf1cdef38, init=<optimized out>, fini=<optimized out>, rtld_fini=<optimized out>, stack_end=0x7ffcf1cdef28) at ../csu/libc-start.c:308
        self = <optimized out>
        __self = <optimized out>
        result = <optimized out>
        unwind_buf = {cancel_jmp_buf = {{jmp_buf = {0, 2299564391826170173, 94716192247232, 140724365291312, 0, 0, 5501701215377924413, 5495476811312374077}, mask_was_saved = 0}}, priv = {pad = {0x0, 0x0, 0x7ff1e0a51b03 <_dl_init+259>, 0x7ff1e043cd80}, data = {prev = 0x0, cleanup = 0x0, canceltype = -526050557}}}
        not_first_call = <optimized out>
#10 0x00005624d4fe4dea in _start ()
No symbol table info available.
--- source code stack trace ---
#0 netsnmp_get (self=<optimized out>, args=<optimized out>) at netsnmp/client_intf.c:1499
  [Error: client_intf.c was not found in source tree]
#1 0x00005624d500e43a in PyEval_EvalFrameEx ()
#2 0x00005624d50130e2 in PyEval_EvalFrameEx ()
#3 0x00005624d500b7da in PyEval_EvalCodeEx ()
#4 0x00005624d503c72f in ?? ()
#5 0x00005624d4f9a46c in PyRun_InteractiveOneFlags ()
#6 0x00005624d4f9a2b8 in PyRun_InteractiveLoopFlags ()
#7 0x00005624d4f7ff7e in ?? ()
#8 0x00005624d4fe54f4 in Py_Main ()
#9 0x00007ff1e045f00a in __libc_start_main (main=0x5624d4fe4ed0 <main>, argc=1, argv=0x7ffcf1cdef38, init=<optimized out>, fini=<optimized out>, rtld_fini=<optimized out>, stack_end=0x7ffcf1cdef28) at ../csu/libc-start.c:308
  [Error: libc-start.c was not found in source tree]
#10 0x00005624d4fe4dea in _start ()

And it seems to match the if-no-list-then-crash as reported by Josh.
There is a loop - simplified:
if (varlist) {
  PyObject *varlist_iter = PyObject_GetIter(varlist);
  [...]
  Py_DECREF(varlist_iter);
}

You see, if the creation failed (for not being a list) then it started at NULL.
And trying to decrement its count is the crash.

Actually when not a list this should refuse kindly.

I coded up what I think (clearly not an net-snmp nor a python bindings expert) is right.
--- a/python/netsnmp/client_intf.c
+++ b/python/netsnmp/client_intf.c
@@ -1471,6 +1471,13 @@ netsnmp_get(PyObject *self, PyObject *args)

     if (varlist) {
       PyObject *varlist_iter = PyObject_GetIter(varlist);
+ if (varlist_iter == NULL) {
+ if (verbose) {
+ printf("error: can't get iterator for varlist");
+ snmp_free_pdu(pdu);
+ goto done;
+ }
+ }

       while (varlist_iter && (varbind = PyIter_Next(varlist_iter))) {
        if (py_netsnmp_attr_string(varbind, "tag", &tag, NULL) < 0 ||

With that compiled and using the library from this build I now get:

>>> vars = netsnmp.Varbind('1.3.6.1.2.1.43.10.2.1.4.1.1')
>>> session.get(vars)
error: can't get iterator for varlist

So it would still be bad usage, but better than a segfault for sure.
OTOH it is not bad enough for a SRU or Ubuntu Delta.
It doesn't work either way.

If net-snmp upstream would not be so dead I'd suggest we report it there ... :-/
Still that might be the right thing to do.