Repository navigation
List of possible bugs found by automated code analysis #17012
Description
I ran an automated code analysis by https://www.deepcode.ai/ and the AI found the following bugs. I'm not sure if all of them are serious or important but if two or three code improvements can be made, that's something at least.
-
1.
"Use binary mode in open [:309] (current mode is w [:309] ) to avoid encoding-related issues for written file, on Windows or with Python 3."numpy/numpy/core/code_generators/genapi.py
Line 309 in e3c5213
with open(filename, 'w') as fid: - See Change mode of open in func write_file() #17054 (withdrawn)
-
2.
Line 162 in e3c5213
if NX.all(NX.sort(roots) == NX.sort(roots.conjugate())): "Use sorted(). sort [:162] sorts in-place and returns None. == [:162] expects a value."np.sortreturns the sorted array and the comparison works elementwise. Thesortedbuiltin applied to a 1D array returns a list and errors for multidimensional arrays.
-
3.
numpy/numpy/core/src/umath/umathmodule.c
Line 203 in e3c5213
strcpy(newdocstr, docstr); "The result of malloc [:202] , which may return null flows [:202, :203] to the first argument [:203] of strcpy [:203] . This could result in undefined behavior. Consider adding a check for nullness." -
4.
"This division [:2228] may result in a division by zero error because 0 [:2046] is a possible divisor."numpy/numpy/core/src/multiarray/nditer_api.c
Line 2228 in e3c5213
(transfersize/reduce_innersize <= - @seberg: I can't see this actually happening. If this would be 0, the buffer and thus the iteration size should be 0, in which case it is invalid to actually iterate.
-
5.
numpy/numpy/linalg/lapack_lite/f2c_lapack.c
Line 708 in e3c5213
} else { "If statement has identical branches."- @charris: Generated code
-
6.
numpy/numpy/linalg/lapack_lite/f2c_lapack.c
Line 1071 in e3c5213
if (ret_val == 1) { "The expression will always evaluate to true because both sides always hold the same value."- @charris: Generated code
-
7.
"Applying unary minus to an unsigned expression. Consider casting the operand to a signed expression before applying minus [:234] ."numpy/numpy/random/src/pcg64/pcg64.h
Line 234 in e3c5213
uint64_t threshold = -bound % bound; -
8. https://github.com/numpy/numpy/blob/e3c52130add2ed5f7f0b9442b3b2742c09eb2de0/benchmarks/benchmarks/common.py#L28-34
"Accessing attribute append [:32] on possibly None value. None flows [:32] as determined by the following check [:31] . Consider adding a check."- @eric-wieser: this is clearly incorrect analysis when looking at the full context
-
9.
" hashlib.sha1 [:402] is insecure. Consider changing it to a secure hashing algorithm (e.g. SHA256)."numpy/numpy/distutils/fcompiler/gnu.py
Line 402 in e3c5213
h = hashlib.sha1() -
10.
"Trying to store [:917] a value in element of immutable type str [:182] (from str literal "" [:182] ) will lead to a crash."numpy/numpy/f2py/crackfortran.py
Line 917 in e3c5213
groupname[groupcounter] = 'program' -
11.
"Trying to call len [:682] on an object of type 0 (0) will lead to a TypeError."numpy/numpy/polynomial/chebyshev.py
Line 682 in e3c5213
if len(c) == 1 and c[0] == 0: -
12.
"There is no need to call list [:562] on an object [:562] that is already constructed as a list [:557] ."numpy/numpy/distutils/command/build_ext.py
Line 562 in e3c5213
for lib in list(libraries): -
13.
"Missing close for open [:1903] , add close or use a with block."numpy/numpy/distutils/misc_util.py
Line 1903 in e3c5213
for line in open(branch_cache_fn, 'r'): -
14.
"If statement has identical branches."numpy/numpy/distutils/fcompiler/gnu.py
Line 26 in e3c5213
if is_win64(): -
15.
"Use comprehensions instead of list [:719] ( map [:718] (lambda: x ...))"numpy/numpy/distutils/system_info.py
Line 718 in e3c5213
found = map(lambda opt: self.cp.has_option(self.section, opt), options) -
16.
"Duplicate expressions on both sides of a logical operator [:1020] is probably a mistake."Line 1020 in e3c5213
truepoly = (isinstance(u, poly1d) or isinstance(u, poly1d)) -
17.
"Trying to load attribute dtype [:426] on an object of primitive type int [:485] (from int literal 0 [:485] ) will lead to an AttributeError."numpy/numpy/polynomial/hermite_e.py
Line 426 in e3c5213
prd = np.empty(len(c) + 1, dtype=c.dtype) -
18.
"Use os.makedirs instead of os.mkdir [:227] because the given path may require creating the parent directories."numpy/tools/openblas_support.py
Line 227 in e3c5213
os.mkdir(target) - See MAINT: Change os.mkdir to os.makedirs #17061 (withdrawn)
-
19.
"There is no need to call set [:391] on an object [:391] that is already constructed as a set [:319] "Line 391 in e3c5213
dep_in_ref = set(only_ref).intersection(deprecated) -
20.
numpy/numpy/core/src/multiarray/iterators.c
Line 517 in e3c5213
Py_DECREF(ret); "Use Py_XDECREF instead of Py_DECREF [:517] "- As pointed out by Eric, obviously cannot be NULL, its checked a few lines earlier.
-
21.
" PyString_FromString [:2603] does not work with Python 3.5, use PyUnicode_FromString instead"numpy/numpy/core/src/multiarray/methods.c
Line 2603 in e3c5213
err = PyString_FromString("unable to convert "); - See MAINT, BUG: Remove uses of PyString_FromString. #17068 for fixes.
-
22.
"Use PyBytes_AsString instead of PyString_AsString [:89] for Python 3 compatibility"ostring = PyString_AsString(sp); -
23.
"Numerical operation lessThan [:268] used with boolean operand equals [:267] . Consider making the conversion from bool to integer explicit."numpy/numpy/f2py/src/fortranobject.c
Line 268 in e3c5213
if (n < 0) { -
24.
"Be aware that an optimizing compiler might be removing this call to memset [:829] , since this axes_dupcheck array [:829] does not seem to be used after the call to memset [:829]."memset(axes_dupcheck, 0, NPY_MAXDIMS); -
25.
"Equals comparison of floating point numbers. Floating point numbers are only considered equal if their bit representation is equal. Consider using an epsilon comparison instead."if (shape == 1.0) { -
26.
"PyString_FromString [:152] does not work with Python 3.5, use PyUnicode_FromString instead"s = PyString_FromString("This module 'wrap' is auto-generated with f2py (version:2_1330).\nFunctions:\n" - See MAINT, BUG: Remove uses of PyString_FromString. #17068 for fixes.
-
27.
"Use Py_XDECREF instead of Py_DECREF [:59] "Py_DECREF(tmp); -
28.
"No need to call keys [:267] , directly check with the in operator."numpy/numpy/lib/_datasource.py
Line 267 in e3c5213
return ext in _file_openers.keys() - See MAINT: Simplify check for key in dictionary #17064 (needs refactoring/rewriting)
-
29.
"Use len() instead of calling len [:494] directly"numpy/numpy/core/tests/test_array_coercion.py
Line 494 in e3c5213
return super().__len__() -
30.
"Use predictable random with seed or secure random."numpy/numpy/core/tests/test_numeric.py
Line 1376 in e3c5213
a = rand(3, 5, 8) -
31.
"Use the is operator instead of == [:496] to compare to None [:496] , because == [:496] calls eq which is slower and error-prone."numpy/numpy/core/tests/test_scalarmath.py
Line 496 in e3c5213
assert_(not np.float32(1) == None) -
32.
"Use comprehensions instead of map [:158] ."numpy/numpy/core/tests/test_shape_base.py
Line 158 in e3c5213
hstack(map(lambda x: x, np.ones((3, 2)))) - See MAINT: Convert lambda func to list comprehension #17065 (withdrawn)
-
33.
"Use del statement instead of calling del [:580] directly"numpy/numpy/lib/_datasource.py
Line 580 in e3c5213
DataSource.__del__(self) -
@charris The current code is recommended when both the base and derived class define the
__del__method. That said, it isn't clear that an explicit__del__is needed, the inherited version should serve.Note del x doesn’t directly call x.del() — the former decrements the reference count
for x by one, and the latter is only called when x’s reference count reaches zero.
-
-
34.
"Use del statement instead of calling del [:350] directly"numpy/numpy/lib/tests/test__datasource.py
Line 350 in e3c5213
ds.__del__() - @charris Calling the function directly insures that it is immediately run at that spot in the test rather than possibly
waiting for the reference count to go to zero. Both options should work here, but I think the direct call is better
because it is more explicit.
- @charris Calling the function directly insures that it is immediately run at that spot in the test rather than possibly
-
35.
"No need to call keys [:2581] , directly check with the in operator."numpy/numpy/lib/tests/test_io.py
Line 2581 in e3c5213
assert_('x' in z.keys())
Activity
charris commentedon Aug 4, 2020
Most of these look reasonable. Note that we no longer support Python < 3.6, the
lapack_litecode is generated by translation from Fortran, and there are compatibility macros innumpy/core/include/numpy/npy_3kcompat.h. I don't know if it is easy for you to use the latter or select the Python versions.charris commentedon Aug 4, 2020
This is not a bug, the
==operator applies element wise to the sorted arrays. Could be made nicer perhaps.EDIT:
sortedreturns a list when applied to arrays. Hmm...eric-wieser commentedon Aug 5, 2020
I've edited the issue text to cross out the cases we've deemed invalid, along with a reason.
bashtage commentedon Aug 5, 2020
7 is clearly wrong. The negation is valid and intentional.
eric-wieser commentedon Aug 5, 2020
@bashtage, I've no idea what
-bound % boundactually does whenboundis an unsigned integerbashtage commentedon Aug 5, 2020
Same as
(-bound) % boundfor an unsigned type. Reflect it around, then find the modulus.This code is never used and could be removed FWIW.
bashtage commentedon Aug 5, 2020
FWIW the idea in this code is to find the amount of a uint64 that is left over after that largest integer divisor, and then remove this from when sampling a bounded integer to produce an unbiased sample.
eric-wieser commentedon Aug 5, 2020
That last comment might be helpful written in the code.
jakobjakobson13 commentedon Aug 9, 2020
I could fix the easy ones (number 1, 12, 13, 14, 15, 16, 18, 19, 20, 22, 27, 28, 32, 35) with the given hints but I don't want to mess with your code. So, should I take action?
seberg commentedon Aug 9, 2020
@jakobjakobson13 sure, PRs are always welcome, if you have time, look at our style guides, etc. but for these small things, I think you can really just go ahead and make a PR. If there are things to fix up, they will be flushed out during review.
eric-wieser commentedon Aug 10, 2020
As far as I can tell 20 is nonsense,
retcannot beNULLon that line.MAINT: Delete obsolete conversion to list (gh-17052)
MAINT: change "for line in open()" to "with open() as f: ..." in nump…
MAINT: Replace lambda function by list comprehension (gh-17055)
rossbar commentedon Aug 11, 2020
@jakobjakobson13 I've reformatted your list in the top comment to be a check list. Can you please double check that the bullets that have been addressed (either with a merged PR, or with a review that decided the change was unnecessary) have been checked? This will give us a clear "definition of done" for the issue to indicate when we can close it.
bashtage commentedon Aug 11, 2020
7 should be ticked and 9 is silly since it is only being used to have a negligible prob of a collision.
melissawm commentedon Sep 24, 2020
23 might be solved by #17373, please let me know if it isn't!
melissawm commentedon Sep 24, 2020
I think 10 is not relevant since these variables are reset at some point in the code.