summaryrefslogtreecommitdiff
path: root/Python
diff options
context:
space:
mode:
Diffstat (limited to 'Python')
-rw-r--r--Python/Python-ast.c2
-rw-r--r--Python/ast.c26
-rw-r--r--Python/bltinmodule.c5
-rw-r--r--Python/compile.c4
-rw-r--r--Python/graminit.c106
-rw-r--r--Python/pythonrun.c10
-rw-r--r--Python/pytime.c254
-rw-r--r--Python/random.c49
8 files changed, 290 insertions, 166 deletions
diff --git a/Python/Python-ast.c b/Python/Python-ast.c
index 8a2dc7cc54..fd7f17e85b 100644
--- a/Python/Python-ast.c
+++ b/Python/Python-ast.c
@@ -769,7 +769,7 @@ static int obj2ast_int(PyObject* obj, int* out, PyArena* arena)
return 1;
}
- i = (int)PyLong_AsLong(obj);
+ i = _PyLong_AsInt(obj);
if (i == -1 && PyErr_Occurred())
return 1;
*out = i;
diff --git a/Python/ast.c b/Python/ast.c
index b2f09b9c84..1f7ddfc197 100644
--- a/Python/ast.c
+++ b/Python/ast.c
@@ -513,7 +513,7 @@ PyAST_Validate(mod_ty mod)
/* Data structure used internally */
struct compiling {
char *c_encoding; /* source encoding */
- PyArena *c_arena; /* arena for allocating memeory */
+ PyArena *c_arena; /* Arena for allocating memory. */
PyObject *c_filename; /* filename */
PyObject *c_normalize; /* Normalization function from unicodedata. */
PyObject *c_normalize_args; /* Normalization argument tuple. */
@@ -1262,16 +1262,20 @@ ast_for_arguments(struct compiling *c, const node *n)
and varargslist (lambda definition).
parameters: '(' [typedargslist] ')'
- typedargslist: ((tfpdef ['=' test] ',')*
- ('*' [tfpdef] (',' tfpdef ['=' test])* [',' '**' tfpdef]
- | '**' tfpdef)
- | tfpdef ['=' test] (',' tfpdef ['=' test])* [','])
+ typedargslist: (tfpdef ['=' test] (',' tfpdef ['=' test])* [',' [
+ '*' [tfpdef] (',' tfpdef ['=' test])* [',' ['**' tfpdef [',']]]
+ | '**' tfpdef [',']]]
+ | '*' [tfpdef] (',' tfpdef ['=' test])* [',' ['**' tfpdef [',']]]
+ | '**' tfpdef [','])
tfpdef: NAME [':' test]
- varargslist: ((vfpdef ['=' test] ',')*
- ('*' [vfpdef] (',' vfpdef ['=' test])* [',' '**' vfpdef]
- | '**' vfpdef)
- | vfpdef ['=' test] (',' vfpdef ['=' test])* [','])
+ varargslist: (vfpdef ['=' test] (',' vfpdef ['=' test])* [',' [
+ '*' [vfpdef] (',' vfpdef ['=' test])* [',' ['**' vfpdef [',']]]
+ | '**' vfpdef [',']]]
+ | '*' [vfpdef] (',' vfpdef ['=' test])* [',' ['**' vfpdef [',']]]
+ | '**' vfpdef [',']
+ )
vfpdef: NAME
+
*/
int i, j, k, nposargs = 0, nkwonlyargs = 0;
int nposdefaults = 0, found_default = 0;
@@ -1373,7 +1377,8 @@ ast_for_arguments(struct compiling *c, const node *n)
i += 2; /* the name and the comma */
break;
case STAR:
- if (i+1 >= NCH(n)) {
+ if (i+1 >= NCH(n) ||
+ (i+2 == NCH(n) && TYPE(CHILD(n, i+1)) == COMMA)) {
ast_error(c, CHILD(n, i),
"named arguments must follow bare *");
return NULL;
@@ -2035,6 +2040,7 @@ ast_for_atom(struct compiling *c, const node *n)
PyOS_snprintf(buf, sizeof(buf), "(%s) %s", errtype, s);
Py_DECREF(errstr);
} else {
+ PyErr_Clear();
PyOS_snprintf(buf, sizeof(buf), "(%s) unknown error", errtype);
}
ast_error(c, n, buf);
diff --git a/Python/bltinmodule.c b/Python/bltinmodule.c
index 2f22209e9d..2038d2b26d 100644
--- a/Python/bltinmodule.c
+++ b/Python/bltinmodule.c
@@ -1158,13 +1158,14 @@ map_next(mapobject *lz)
PyObject *result;
Py_ssize_t numargs, i;
- numargs = PyTuple_Size(lz->iters);
+ numargs = PyTuple_GET_SIZE(lz->iters);
argtuple = PyTuple_New(numargs);
if (argtuple == NULL)
return NULL;
for (i=0 ; i<numargs ; i++) {
- val = PyIter_Next(PyTuple_GET_ITEM(lz->iters, i));
+ PyObject *it = PyTuple_GET_ITEM(lz->iters, i);
+ val = Py_TYPE(it)->tp_iternext(it);
if (val == NULL) {
Py_DECREF(argtuple);
return NULL;
diff --git a/Python/compile.c b/Python/compile.c
index 97bb12ee67..a6884ec211 100644
--- a/Python/compile.c
+++ b/Python/compile.c
@@ -3628,9 +3628,9 @@ expr_constant(struct compiler *c, expr_ty e)
BLOCK
finally:
if an exception was raised:
- exc = copy of (exception, instance, traceback)
+ exc = copy of (exception, instance, traceback)
else:
- exc = (None, None, None)
+ exc = (None, None, None)
if not (await exit(*exc)):
raise
*/
diff --git a/Python/graminit.c b/Python/graminit.c
index 8212b2a584..354dc121b0 100644
--- a/Python/graminit.c
+++ b/Python/graminit.c
@@ -204,11 +204,13 @@ static arc arcs_9_6[2] = {
{32, 7},
{0, 6},
};
-static arc arcs_9_7[2] = {
+static arc arcs_9_7[3] = {
{30, 12},
{34, 3},
+ {0, 7},
};
-static arc arcs_9_8[1] = {
+static arc arcs_9_8[2] = {
+ {32, 13},
{0, 8},
};
static arc arcs_9_9[2] = {
@@ -221,35 +223,39 @@ static arc arcs_9_10[3] = {
{0, 10},
};
static arc arcs_9_11[3] = {
- {30, 13},
- {32, 14},
+ {30, 14},
+ {32, 15},
{0, 11},
};
static arc arcs_9_12[3] = {
{32, 7},
- {31, 15},
+ {31, 16},
{0, 12},
};
-static arc arcs_9_13[2] = {
- {32, 14},
+static arc arcs_9_13[1] = {
{0, 13},
};
static arc arcs_9_14[2] = {
- {30, 16},
+ {32, 15},
+ {0, 14},
+};
+static arc arcs_9_15[3] = {
+ {30, 17},
{34, 3},
+ {0, 15},
};
-static arc arcs_9_15[1] = {
+static arc arcs_9_16[1] = {
{26, 6},
};
-static arc arcs_9_16[3] = {
- {32, 14},
- {31, 17},
- {0, 16},
+static arc arcs_9_17[3] = {
+ {32, 15},
+ {31, 18},
+ {0, 17},
};
-static arc arcs_9_17[1] = {
- {26, 13},
+static arc arcs_9_18[1] = {
+ {26, 14},
};
-static state states_9[18] = {
+static state states_9[19] = {
{3, arcs_9_0},
{3, arcs_9_1},
{3, arcs_9_2},
@@ -257,17 +263,18 @@ static state states_9[18] = {
{1, arcs_9_4},
{4, arcs_9_5},
{2, arcs_9_6},
- {2, arcs_9_7},
- {1, arcs_9_8},
+ {3, arcs_9_7},
+ {2, arcs_9_8},
{2, arcs_9_9},
{3, arcs_9_10},
{3, arcs_9_11},
{3, arcs_9_12},
- {2, arcs_9_13},
+ {1, arcs_9_13},
{2, arcs_9_14},
- {1, arcs_9_15},
- {3, arcs_9_16},
- {1, arcs_9_17},
+ {3, arcs_9_15},
+ {1, arcs_9_16},
+ {3, arcs_9_17},
+ {1, arcs_9_18},
};
static arc arcs_10_0[1] = {
{23, 1},
@@ -319,11 +326,13 @@ static arc arcs_11_6[2] = {
{32, 7},
{0, 6},
};
-static arc arcs_11_7[2] = {
+static arc arcs_11_7[3] = {
{36, 12},
{34, 3},
+ {0, 7},
};
-static arc arcs_11_8[1] = {
+static arc arcs_11_8[2] = {
+ {32, 13},
{0, 8},
};
static arc arcs_11_9[2] = {
@@ -336,35 +345,39 @@ static arc arcs_11_10[3] = {
{0, 10},
};
static arc arcs_11_11[3] = {
- {36, 13},
- {32, 14},
+ {36, 14},
+ {32, 15},
{0, 11},
};
static arc arcs_11_12[3] = {
{32, 7},
- {31, 15},
+ {31, 16},
{0, 12},
};
-static arc arcs_11_13[2] = {
- {32, 14},
+static arc arcs_11_13[1] = {
{0, 13},
};
static arc arcs_11_14[2] = {
- {36, 16},
+ {32, 15},
+ {0, 14},
+};
+static arc arcs_11_15[3] = {
+ {36, 17},
{34, 3},
+ {0, 15},
};
-static arc arcs_11_15[1] = {
+static arc arcs_11_16[1] = {
{26, 6},
};
-static arc arcs_11_16[3] = {
- {32, 14},
- {31, 17},
- {0, 16},
+static arc arcs_11_17[3] = {
+ {32, 15},
+ {31, 18},
+ {0, 17},
};
-static arc arcs_11_17[1] = {
- {26, 13},
+static arc arcs_11_18[1] = {
+ {26, 14},
};
-static state states_11[18] = {
+static state states_11[19] = {
{3, arcs_11_0},
{3, arcs_11_1},
{3, arcs_11_2},
@@ -372,17 +385,18 @@ static state states_11[18] = {
{1, arcs_11_4},
{4, arcs_11_5},
{2, arcs_11_6},
- {2, arcs_11_7},
- {1, arcs_11_8},
+ {3, arcs_11_7},
+ {2, arcs_11_8},
{2, arcs_11_9},
{3, arcs_11_10},
{3, arcs_11_11},
{3, arcs_11_12},
- {2, arcs_11_13},
+ {1, arcs_11_13},
{2, arcs_11_14},
- {1, arcs_11_15},
- {3, arcs_11_16},
- {1, arcs_11_17},
+ {3, arcs_11_15},
+ {1, arcs_11_16},
+ {3, arcs_11_17},
+ {1, arcs_11_18},
};
static arc arcs_12_0[1] = {
{23, 1},
@@ -1879,11 +1893,11 @@ static dfa dfas[85] = {
"\000\000\100\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"},
{264, "parameters", 0, 4, states_8,
"\000\040\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"},
- {265, "typedargslist", 0, 18, states_9,
+ {265, "typedargslist", 0, 19, states_9,
"\000\000\200\000\006\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"},
{266, "tfpdef", 0, 4, states_10,
"\000\000\200\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"},
- {267, "varargslist", 0, 18, states_11,
+ {267, "varargslist", 0, 19, states_11,
"\000\000\200\000\006\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"},
{268, "vfpdef", 0, 2, states_12,
"\000\000\200\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"},
diff --git a/Python/pythonrun.c b/Python/pythonrun.c
index ebedd123f3..1a5dab5f3a 100644
--- a/Python/pythonrun.c
+++ b/Python/pythonrun.c
@@ -431,7 +431,7 @@ static int
parse_syntax_error(PyObject *err, PyObject **message, PyObject **filename,
int *lineno, int *offset, PyObject **text)
{
- long hold;
+ int hold;
PyObject *v;
_Py_IDENTIFIER(msg);
_Py_IDENTIFIER(filename);
@@ -464,11 +464,11 @@ parse_syntax_error(PyObject *err, PyObject **message, PyObject **filename,
v = _PyObject_GetAttrId(err, &PyId_lineno);
if (!v)
goto finally;
- hold = PyLong_AsLong(v);
+ hold = _PyLong_AsInt(v);
Py_DECREF(v);
if (hold < 0 && PyErr_Occurred())
goto finally;
- *lineno = (int)hold;
+ *lineno = hold;
v = _PyObject_GetAttrId(err, &PyId_offset);
if (!v)
@@ -477,11 +477,11 @@ parse_syntax_error(PyObject *err, PyObject **message, PyObject **filename,
*offset = -1;
Py_DECREF(v);
} else {
- hold = PyLong_AsLong(v);
+ hold = _PyLong_AsInt(v);
Py_DECREF(v);
if (hold < 0 && PyErr_Occurred())
goto finally;
- *offset = (int)hold;
+ *offset = hold;
}
v = _PyObject_GetAttrId(err, &PyId_text);
diff --git a/Python/pytime.c b/Python/pytime.c
index 5a5cdd9c7a..9889a3b53b 100644
--- a/Python/pytime.c
+++ b/Python/pytime.c
@@ -7,6 +7,11 @@
#include <mach/mach_time.h> /* mach_absolute_time(), mach_timebase_info() */
#endif
+#define _PyTime_check_mul_overflow(a, b) \
+ (assert(b > 0), \
+ (_PyTime_t)(a) < _PyTime_MIN / (_PyTime_t)(b) \
+ || _PyTime_MAX / (_PyTime_t)(b) < (_PyTime_t)(a))
+
/* To millisecond (10^-3) */
#define SEC_TO_MS 1000
@@ -60,50 +65,83 @@ _PyLong_FromTime_t(time_t t)
#endif
}
+/* Round to nearest with ties going to nearest even integer
+ (_PyTime_ROUND_HALF_EVEN) */
+static double
+_PyTime_RoundHalfEven(double x)
+{
+ double rounded = round(x);
+ if (fabs(x-rounded) == 0.5)
+ /* halfway case: round to even */
+ rounded = 2.0*round(x/2.0);
+ return rounded;
+}
+
+static double
+_PyTime_Round(double x, _PyTime_round_t round)
+{
+ /* volatile avoids optimization changing how numbers are rounded */
+ volatile double d;
+
+ d = x;
+ if (round == _PyTime_ROUND_HALF_EVEN)
+ d = _PyTime_RoundHalfEven(d);
+ else if (round == _PyTime_ROUND_CEILING)
+ d = ceil(d);
+ else
+ d = floor(d);
+ return d;
+}
+
static int
-_PyTime_ObjectToDenominator(PyObject *obj, time_t *sec, long *numerator,
+_PyTime_DoubleToDenominator(double d, time_t *sec, long *numerator,
double denominator, _PyTime_round_t round)
{
- assert(denominator <= LONG_MAX);
- if (PyFloat_Check(obj)) {
- double d, intpart, err;
- /* volatile avoids unsafe optimization on float enabled by gcc -O3 */
- volatile double floatpart;
+ double intpart, err;
+ /* volatile avoids optimization changing how numbers are rounded */
+ volatile double floatpart;
- d = PyFloat_AsDouble(obj);
- floatpart = modf(d, &intpart);
- if (floatpart < 0) {
- floatpart = 1.0 + floatpart;
- intpart -= 1.0;
- }
+ floatpart = modf(d, &intpart);
- floatpart *= denominator;
- if (round == _PyTime_ROUND_CEILING) {
- floatpart = ceil(floatpart);
- if (floatpart >= denominator) {
- floatpart = 0.0;
- intpart += 1.0;
- }
- }
- else {
- floatpart = floor(floatpart);
- }
+ floatpart *= denominator;
+ floatpart = _PyTime_Round(floatpart, round);
+ if (floatpart >= denominator) {
+ floatpart -= denominator;
+ intpart += 1.0;
+ }
+ else if (floatpart < 0) {
+ floatpart += denominator;
+ intpart -= 1.0;
+ }
+ assert(0.0 <= floatpart && floatpart < denominator);
- *sec = (time_t)intpart;
- err = intpart - (double)*sec;
- if (err <= -1.0 || err >= 1.0) {
- error_time_t_overflow();
- return -1;
- }
+ *sec = (time_t)intpart;
+ *numerator = (long)floatpart;
- *numerator = (long)floatpart;
- return 0;
+ err = intpart - (double)*sec;
+ if (err <= -1.0 || err >= 1.0) {
+ error_time_t_overflow();
+ return -1;
+ }
+ return 0;
+}
+
+static int
+_PyTime_ObjectToDenominator(PyObject *obj, time_t *sec, long *numerator,
+ double denominator, _PyTime_round_t round)
+{
+ assert(denominator <= (double)LONG_MAX);
+
+ if (PyFloat_Check(obj)) {
+ double d = PyFloat_AsDouble(obj);
+ return _PyTime_DoubleToDenominator(d, sec, numerator,
+ denominator, round);
}
else {
*sec = _PyLong_AsTime_t(obj);
+ *numerator = 0;
if (*sec == (time_t)-1 && PyErr_Occurred())
return -1;
- *numerator = 0;
return 0;
}
}
@@ -112,13 +150,12 @@ int
_PyTime_ObjectToTime_t(PyObject *obj, time_t *sec, _PyTime_round_t round)
{
if (PyFloat_Check(obj)) {
- double d, intpart, err;
+ double intpart, err;
+ /* volatile avoids optimization changing how numbers are rounded */
+ volatile double d;
d = PyFloat_AsDouble(obj);
- if (round == _PyTime_ROUND_CEILING)
- d = ceil(d);
- else
- d = floor(d);
+ d = _PyTime_Round(d, round);
(void)modf(d, &intpart);
*sec = (time_t)intpart;
@@ -141,14 +178,20 @@ int
_PyTime_ObjectToTimespec(PyObject *obj, time_t *sec, long *nsec,
_PyTime_round_t round)
{
- return _PyTime_ObjectToDenominator(obj, sec, nsec, 1e9, round);
+ int res;
+ res = _PyTime_ObjectToDenominator(obj, sec, nsec, 1e9, round);
+ assert(0 <= *nsec && *nsec < SEC_TO_NS);
+ return res;
}
int
_PyTime_ObjectToTimeval(PyObject *obj, time_t *sec, long *usec,
_PyTime_round_t round)
{
- return _PyTime_ObjectToDenominator(obj, sec, usec, 1e6, round);
+ int res;
+ res = _PyTime_ObjectToDenominator(obj, sec, usec, 1e6, round);
+ assert(0 <= *usec && *usec < SEC_TO_US);
+ return res;
}
static void
@@ -162,12 +205,13 @@ _PyTime_t
_PyTime_FromSeconds(int seconds)
{
_PyTime_t t;
+ t = (_PyTime_t)seconds;
/* ensure that integer overflow cannot happen, int type should have 32
bits, whereas _PyTime_t type has at least 64 bits (SEC_TO_MS takes 30
bits). */
- assert((seconds >= 0 && seconds <= _PyTime_MAX / SEC_TO_NS)
- || (seconds < 0 && seconds >= _PyTime_MIN / SEC_TO_NS));
- t = (_PyTime_t)seconds * SEC_TO_NS;
+ assert((t >= 0 && t <= _PyTime_MAX / SEC_TO_NS)
+ || (t < 0 && t >= _PyTime_MIN / SEC_TO_NS));
+ t *= SEC_TO_NS;
return t;
}
@@ -187,12 +231,15 @@ _PyTime_FromTimespec(_PyTime_t *tp, struct timespec *ts, int raise)
_PyTime_t t;
int res = 0;
- t = (_PyTime_t)ts->tv_sec * SEC_TO_NS;
- if (t / SEC_TO_NS != ts->tv_sec) {
+ assert(sizeof(ts->tv_sec) <= sizeof(_PyTime_t));
+ t = (_PyTime_t)ts->tv_sec;
+
+ if (_PyTime_check_mul_overflow(t, SEC_TO_NS)) {
if (raise)
_PyTime_overflow();
res = -1;
}
+ t = t * SEC_TO_NS;
t += ts->tv_nsec;
@@ -206,12 +253,15 @@ _PyTime_FromTimeval(_PyTime_t *tp, struct timeval *tv, int raise)
_PyTime_t t;
int res = 0;
- t = (_PyTime_t)tv->tv_sec * SEC_TO_NS;
- if (t / SEC_TO_NS != tv->tv_sec) {
+ assert(sizeof(tv->tv_sec) <= sizeof(_PyTime_t));
+ t = (_PyTime_t)tv->tv_sec;
+
+ if (_PyTime_check_mul_overflow(t, SEC_TO_NS)) {
if (raise)
_PyTime_overflow();
res = -1;
}
+ t = t * SEC_TO_NS;
t += (_PyTime_t)tv->tv_usec * US_TO_NS;
@@ -221,50 +271,59 @@ _PyTime_FromTimeval(_PyTime_t *tp, struct timeval *tv, int raise)
#endif
static int
-_PyTime_FromObject(_PyTime_t *t, PyObject *obj, _PyTime_round_t round,
- long to_nanoseconds)
+_PyTime_FromFloatObject(_PyTime_t *t, double value, _PyTime_round_t round,
+ long unit_to_ns)
{
- if (PyFloat_Check(obj)) {
- /* volatile avoids unsafe optimization on float enabled by gcc -O3 */
- volatile double d, err;
+ double err;
+ /* volatile avoids optimization changing how numbers are rounded */
+ volatile double d;
- /* convert to a number of nanoseconds */
- d = PyFloat_AsDouble(obj);
- d *= to_nanoseconds;
+ /* convert to a number of nanoseconds */
+ d = value;
+ d *= (double)unit_to_ns;
+ d = _PyTime_Round(d, round);
- if (round == _PyTime_ROUND_CEILING)
- d = ceil(d);
- else
- d = floor(d);
+ *t = (_PyTime_t)d;
+ err = d - (double)*t;
+ if (fabs(err) >= 1.0) {
+ _PyTime_overflow();
+ return -1;
+ }
+ return 0;
+}
- *t = (_PyTime_t)d;
- err = d - (double)*t;
- if (fabs(err) >= 1.0) {
- _PyTime_overflow();
- return -1;
- }
- return 0;
+static int
+_PyTime_FromObject(_PyTime_t *t, PyObject *obj, _PyTime_round_t round,
+ long unit_to_ns)
+{
+ if (PyFloat_Check(obj)) {
+ double d;
+ d = PyFloat_AsDouble(obj);
+ return _PyTime_FromFloatObject(t, d, round, unit_to_ns);
}
else {
#ifdef HAVE_LONG_LONG
PY_LONG_LONG sec;
- sec = PyLong_AsLongLong(obj);
assert(sizeof(PY_LONG_LONG) <= sizeof(_PyTime_t));
+
+ sec = PyLong_AsLongLong(obj);
#else
long sec;
- sec = PyLong_AsLong(obj);
assert(sizeof(PY_LONG_LONG) <= sizeof(_PyTime_t));
+
+ sec = PyLong_AsLong(obj);
#endif
if (sec == -1 && PyErr_Occurred()) {
if (PyErr_ExceptionMatches(PyExc_OverflowError))
_PyTime_overflow();
return -1;
}
- *t = sec * to_nanoseconds;
- if (*t / to_nanoseconds != sec) {
+
+ if (_PyTime_check_mul_overflow(sec, unit_to_ns)) {
_PyTime_overflow();
return -1;
}
+ *t = sec * unit_to_ns;
return 0;
}
}
@@ -284,12 +343,21 @@ _PyTime_FromMillisecondsObject(_PyTime_t *t, PyObject *obj, _PyTime_round_t roun
double
_PyTime_AsSecondsDouble(_PyTime_t t)
{
- _PyTime_t sec, ns;
- /* Divide using integers to avoid rounding issues on the integer part.
- 1e-9 cannot be stored exactly in IEEE 64-bit. */
- sec = t / SEC_TO_NS;
- ns = t % SEC_TO_NS;
- return (double)sec + (double)ns * 1e-9;
+ /* volatile avoids optimization changing how numbers are rounded */
+ volatile double d;
+
+ if (t % SEC_TO_NS == 0) {
+ _PyTime_t secs;
+ /* Divide using integers to avoid rounding issues on the integer part.
+ 1e-9 cannot be stored exactly in IEEE 64-bit. */
+ secs = t / SEC_TO_NS;
+ d = (double)secs;
+ }
+ else {
+ d = (double)t;
+ d /= 1e9;
+ }
+ return d;
}
PyObject *
@@ -309,7 +377,20 @@ _PyTime_Divide(const _PyTime_t t, const _PyTime_t k,
const _PyTime_round_t round)
{
assert(k > 1);
- if (round == _PyTime_ROUND_CEILING) {
+ if (round == _PyTime_ROUND_HALF_EVEN) {
+ _PyTime_t x, r, abs_r;
+ x = t / k;
+ r = t % k;
+ abs_r = Py_ABS(r);
+ if (abs_r > k / 2 || (abs_r == k / 2 && (Py_ABS(x) & 1))) {
+ if (t >= 0)
+ x++;
+ else
+ x--;
+ }
+ return x;
+ }
+ else if (round == _PyTime_ROUND_CEILING) {
if (t >= 0)
return (t + k - 1) / k;
else
@@ -424,6 +505,7 @@ _PyTime_AsTimevalTime_t(_PyTime_t t, time_t *p_secs, int *us,
return 0;
}
+
#if defined(HAVE_CLOCK_GETTIME) || defined(HAVE_KQUEUE)
int
_PyTime_AsTimespec(_PyTime_t t, struct timespec *ts)
@@ -437,13 +519,13 @@ _PyTime_AsTimespec(_PyTime_t t, struct timespec *ts)
secs -= 1;
}
ts->tv_sec = (time_t)secs;
+ assert(0 <= nsec && nsec < SEC_TO_NS);
+ ts->tv_nsec = nsec;
+
if ((_PyTime_t)ts->tv_sec != secs) {
- _PyTime_overflow();
+ error_time_t_overflow();
return -1;
}
- ts->tv_nsec = nsec;
-
- assert(0 <= ts->tv_nsec && ts->tv_nsec <= 999999999);
return 0;
}
#endif
@@ -557,19 +639,20 @@ _PyTime_GetSystemClockWithInfo(_PyTime_t *t, _Py_clock_info_t *info)
return pygettimeofday_new(t, info, 1);
}
-
static int
pymonotonic(_PyTime_t *tp, _Py_clock_info_t *info, int raise)
{
#if defined(MS_WINDOWS)
- ULONGLONG result;
+ ULONGLONG ticks;
+ _PyTime_t t;
assert(info == NULL || raise);
- result = GetTickCount64();
+ ticks = GetTickCount64();
+ assert(sizeof(ticks) <= sizeof(_PyTime_t));
+ t = (_PyTime_t)ticks;
- *tp = result * MS_TO_NS;
- if (*tp / MS_TO_NS != result) {
+ if (_PyTime_check_mul_overflow(t, MS_TO_NS)) {
if (raise) {
_PyTime_overflow();
return -1;
@@ -577,6 +660,7 @@ pymonotonic(_PyTime_t *tp, _Py_clock_info_t *info, int raise)
/* Hello, time traveler! */
assert(0);
}
+ *tp = t * MS_TO_NS;
if (info) {
DWORD timeAdjustment, timeIncrement;
diff --git a/Python/random.c b/Python/random.c
index ea09e84a7b..8f3e6d6021 100644
--- a/Python/random.c
+++ b/Python/random.c
@@ -6,7 +6,9 @@
# ifdef HAVE_SYS_STAT_H
# include <sys/stat.h>
# endif
-# ifdef HAVE_GETRANDOM_SYSCALL
+# ifdef HAVE_GETRANDOM
+# include <sys/random.h>
+# elif defined(HAVE_GETRANDOM_SYSCALL)
# include <sys/syscall.h>
# endif
#endif
@@ -70,7 +72,9 @@ win32_urandom(unsigned char *buffer, Py_ssize_t size, int raise)
return 0;
}
-#elif HAVE_GETENTROPY
+#elif defined(HAVE_GETENTROPY) && !defined(sun)
+#define PY_GETENTROPY
+
/* Fill buffer with size pseudo-random bytes generated by getentropy().
Return 0 on success, or raise an exception and return -1 on error.
@@ -105,16 +109,19 @@ py_getentropy(unsigned char *buffer, Py_ssize_t size, int fatal)
return 0;
}
-#else /* !HAVE_GETENTROPY */
+#else
+
+#if defined(HAVE_GETRANDOM) || defined(HAVE_GETRANDOM_SYSCALL)
+#define PY_GETRANDOM
-#ifdef HAVE_GETRANDOM_SYSCALL
static int
py_getrandom(void *buffer, Py_ssize_t size, int raise)
{
- /* is getrandom() supported by the running kernel?
- * need Linux kernel 3.17 or later */
+ /* Is getrandom() supported by the running kernel?
+ * Need Linux kernel 3.17 or newer, or Solaris 11.3 or newer */
static int getrandom_works = 1;
- /* Use /dev/urandom, block if the kernel has no entropy */
+ /* Use non-blocking /dev/urandom device. On Linux at boot, the getrandom()
+ * syscall blocks until /dev/urandom is initialized with enough entropy. */
const int flags = 0;
int n;
@@ -124,7 +131,18 @@ py_getrandom(void *buffer, Py_ssize_t size, int raise)
while (0 < size) {
errno = 0;
- /* Use syscall() because the libc doesn't expose getrandom() yet, see:
+#ifdef HAVE_GETRANDOM
+ if (raise) {
+ Py_BEGIN_ALLOW_THREADS
+ n = getrandom(buffer, size, flags);
+ Py_END_ALLOW_THREADS
+ }
+ else {
+ n = getrandom(buffer, size, flags);
+ }
+#else
+ /* On Linux, use the syscall() function because the GNU libc doesn't
+ * expose the Linux getrandom() syscall yet. See:
* https://sourceware.org/bugzilla/show_bug.cgi?id=17252 */
if (raise) {
Py_BEGIN_ALLOW_THREADS
@@ -134,6 +152,7 @@ py_getrandom(void *buffer, Py_ssize_t size, int raise)
else {
n = syscall(SYS_getrandom, buffer, size, flags);
}
+#endif
if (n < 0) {
if (errno == ENOSYS) {
@@ -182,7 +201,7 @@ dev_urandom_noraise(unsigned char *buffer, Py_ssize_t size)
assert (0 < size);
-#ifdef HAVE_GETRANDOM_SYSCALL
+#ifdef PY_GETRANDOM
if (py_getrandom(buffer, size, 0) == 1)
return;
/* getrandom() is not supported by the running kernel, fall back
@@ -218,14 +237,14 @@ dev_urandom_python(char *buffer, Py_ssize_t size)
int fd;
Py_ssize_t n;
struct _Py_stat_struct st;
-#ifdef HAVE_GETRANDOM_SYSCALL
+#ifdef PY_GETRANDOM
int res;
#endif
if (size <= 0)
return 0;
-#ifdef HAVE_GETRANDOM_SYSCALL
+#ifdef PY_GETRANDOM
res = py_getrandom(buffer, size, 1);
if (res < 0)
return -1;
@@ -304,7 +323,7 @@ dev_urandom_close(void)
}
}
-#endif /* HAVE_GETENTROPY */
+#endif
/* Fill buffer with pseudo-random bytes generated by a linear congruent
generator (LCG):
@@ -345,7 +364,7 @@ _PyOS_URandom(void *buffer, Py_ssize_t size)
#ifdef MS_WINDOWS
return win32_urandom((unsigned char *)buffer, size, 1);
-#elif HAVE_GETENTROPY
+#elif PY_GETENTROPY
return py_getentropy(buffer, size, 0);
#else
return dev_urandom_python((char*)buffer, size);
@@ -392,7 +411,7 @@ _PyRandom_Init(void)
else {
#ifdef MS_WINDOWS
(void)win32_urandom(secret, secret_size, 0);
-#elif HAVE_GETENTROPY
+#elif PY_GETENTROPY
(void)py_getentropy(secret, secret_size, 1);
#else
dev_urandom_noraise(secret, secret_size);
@@ -408,7 +427,7 @@ _PyRandom_Fini(void)
CryptReleaseContext(hCryptProv, 0);
hCryptProv = 0;
}
-#elif HAVE_GETENTROPY
+#elif PY_GETENTROPY
/* nothing to clean */
#else
dev_urandom_close();