This document is developed based on PEP 8, Huawei Python Coding Style Guide, Huawei Python Secure Coding Standard, and industry consensus. To participate in the MindSpore community, please comply with this style guide (for contents conflict with the PEP 8 style guide), and then with PEP 8.
If you disagree with the rules, you are advised to submit an issue and provide reasons. The issue can take effect after being reviewed, accepted, and modified by the MindSpore community operation team.
MindSpore open source community
class _Foo:
_instance = None
pass
def _func_example(path):
pass
If a line contains more than 120 characters, start a new line properly.
All Python files must contain the following copyright statements:
# Copyright 2019 Huawei Technologies Co., Ltd
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# ============================================================================
"""
Add notes.
"""
import xxx
Notes:
Files created in 2020 should containCopyright 2020 Huawei Technologies Co., Ltd
.
Files created in 2019 and modified in 2020 should containCopyright 2019-2020 Huawei Technologies Co., Ltd
.
class
and def
are the same. Use Python comments which is generally accepted by the industry, and indent the comments under a declaration. All class
and def
should be commented. You can write only one introduction for the classes and methods in the module.A file path that comes from external data must be canonicalized first. If the file path is not canonicalized, attackers can construct a malicious file path to access the file without authorization.
For example, an attacker can construct ../../../etc/passwd to access any file.
For example, use the realpath() function in Linux and the PathCanonicalize() function in Windows for file path canonicalization.
[Noncompliant Code Example]
The following code obtains the file name from an external system, concatenates the file name into a file path, and directly reads the file content. As a result, the attacker can read the content of any file.
The following is an example of error code:
[Compliant Code Example]
Canonicalize the file path and then check whether the path is valid in the program.
The following is an example of correct code:
[Exceptions]
Command line programs that run on the console, or file paths that are manually entered on the console are exempted from this rule.
If untrusted input that is not verified is used as a parameter or part of a system command, vulnerability may occur in a command injection. For the command injection vulnerability, the command is executed at the same privilege level as the Python application. It provides a function similar to shells for attackers. In Python, os.system or os.popen is often used to call a new process. If the command to be executed comes from external input, command and parameter injection may occur.
When running the command, pay attention to the following points:
[Noncompliant Code Example 1]
The attacker can find the value of the environment variable APPHOME and place the attacking program against the constant INITCMD in the corresponding directory
to execute the attack.
home = os.getenv('APPHOME')
cmd = os.path.join(home, INITCMD)
os.system(cmd)
[Noncompliant Code Example 2]
The value of the backuptype attribute is not verified. The value is entered by the user and may be attacked. For example, the value entered by the user is && del.
c:\dbms\. ":
# The value is obtained from the user configuration.
btype = req.field('backuptype')
cmd = "cmd.exe /K \"c:\\util\\rmanDB.bat " + btype + "&&c:\\util\\cleanup.bat\""
os.system(cmd)
[Noncompliant Code Example 3]
The value of the backuptype attribute is not verified. The value is entered by the user, which may be attacked. For example, the value entered by the user is && del.
c:\dbms\. ":
import os
import sys
try:
print(os.system("ls " + sys.argv[1]))
except Exception as ex:
print('exception:', ex)
Attackers can run the following command to exploit this vulnerability:
python test.py ". && echo bad"
Actually, the following two commands are executed:
ls .
echo bad
[Compliant Code Example]
Do not use os.system. You can use standard APIs instead of running system commands to complete the tasks.
import os
import sys
try:
print(os.listdir(sys.argv[1]))
except Exception as ex:
print(ex)
Ensure that the programs in each except block continue to operate only when they are valid. The except block must either recover from an exception or throw another exception suitable for the context of the current catch block to allow the most adjacent outer try-except statement block to recover.
[Compliant Code Example]
The correct method is to avoid using os.system. You can use standard APIs instead of running system commands to complete the tasks.
validFlag = False
while not validFlag:
try:
# If requested file does not exist, throws FileNotFoundError
# If requested file exists, sets validFlag to true
validFlag = True
except FileNotFoundError:
import traceback
traceback.print_exc()
[Exceptions]
When using try…except… to protect the code, if an exception occurs during code execution, use finally… to ensure that operation objects can be released.
[Compliant Code Example]
handle = open(r"/tmp/sample_data.txt") # May raise IOError
try:
data = handle.read() # May raise UnicodeDecodeError
except UnicodeDecodeError as decode_error:
print(decode_error)
finally:
handle.close() # Always run after try:
Note that Python is tolerant of exceptions. The "except:" statement can capture any errors, including those in Python syntax. Executing the "except:" statement hides potential bugs. Therefore, specify exceptions to be handled when using try…except… to protect the code. The Exception class is the base class of most runtime exceptions and should not be used in the "except:" statement. The "try" statement should contain only exceptions that must be handled at the current location. The "except:" statement should only capture exceptions that must be handled. For example, for the code for opening files, the "try" statement should contain only the "open" statement. The "except:" statement only captures the FileNotFoundError exceptions. Other unexpected exceptions are captured by functions in the upper layer, or are transparently transmitted to external programs for exposure.
[Noncompliant Code Example]
Two types of exceptions may occur in the following code. When executing the "except:" statement for unified handle, if exceptions occur in the open statement execution, and the "except:" statement handle is invalid, the close method will be called and an error that the reported handle is undefined will be reported.
try:
handle = open(r"/tmp/sample_data.txt") # May raise IOError
data = handle.read() # May raise UnicodeDecodeError
except:
handle.close()
[Compliant Code Example]
try:
handle = open(r"/tmp/sample_data.txt") # May raise IOError
try:
data = handle.read() # May raise UnicodeDecodeError
except UnicodeDecodeError as decode_error:
print(decode_error)
finally:
handle.close()
except(FileNotFoundError, IOError) as file_open_except:
print(file_open_except)
Note: The raise keyword can be used only in the "try-except" statement and re-throw exceptions captured by the "except:" statement.
[Noncompliant Code Example]
a = 1
if a==1:
raise
[Compliant Code Example 1] Raise an exception or a custom exception.
a = 1
if a==1:
raise Exception
[Compliant Code Example 2] Use the raise keyword in the "try-except" statement.
try:
f = open('myfile.txt')
s = f.readline()
i = int(s.strip())
except IOError as e:
print("I/O error({0}): {1}".format(e.errno, e.strerror))
except ValueError:
print("Could not convert data to an integer.")
except Exception:
print("Unexpected error:", sys.exc_info()[0])
raise
Python implements the random number generation function in the random module, and implements various distributed pseudo-random number generators. The generated random numbers can be
evenly distributed, in Gaussian distribution, logarithmic normal distribution, negative exponential distribution, alpha distribution, or beta distribution manners. However, these random numbers are pseudo-random numbers, and
cannot be used for applications requiring security encryption.
Use /dev/random to generate secure random numbers, or use the secrets module introduced by Python 3.6 to generate secure random numbers.
[Noncompliant Code Example]
import random
# Pseudo-random numbers
func = random.SystemRandom()
print(func.random())
print(func.randint(0, 10))
[Compliant Code Example]
import platform
# For details about the length, see the cryptographic algorithm specifications. The length varies according to the scenario.
randLength = 16
if platform.system() == 'Linux':
with open("/dev/random", 'rb') as file:
sr = file.read(randLength)
print(sr)
The assert statement is used only for internal tests during R&D. If AssertionError occurs, it indicates that errors exist in software design or the code.
The software should be modified to resolve this issue. Do not include the assert function in externally released versions for production.