New submission from Dmitry Marakasov <[email protected]>:
So, I was investigating a test failure of python 3.11 and 3.10 on FreeBSD (but
it likely applies to all python versions):
======================================================================
FAIL: test_makedev (test.test_posix.PosixTester)
----------------------------------------------------------------------
Traceback (most recent call last):
File "/usr/ports/lang/python311/work/Python-3.11.0a1/Lib/test/test_posix.py",
line 686, in test_makedev
self.assertGreaterEqual(dev, 0)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
AssertionError: -5228656221359548839 not greater than or equal to 0
----------------------------------------------------------------------
The test checks that posix.stat(somepath).st_dev >= 0, but negative value was
returned.
Python uses PyLong_FromLongLong to convert from dev_t C type which st_dev is:
https://github.com/python/cpython/blob/main/Modules/posixmodule.c#L2410
https://github.com/python/cpython/blob/main/Modules/posixmodule.c#L901
POSIX does not seem to define signedness of dev_t,
https://pubs.opengroup.org/onlinepubs/9699919799.2018edition/basedefs/sys_types.h.html
only saying it shall be an "integer type". However on practice on both FreeBSD
and Linux it's unsigned:
FreeBSD:
typedef __dev_t dev_t; // sys/types.h
typedef __uint64_t __dev_t; // sys/_types.h
Linux (Ubuntu 18.04):
typedef __dev_t dev_t; // sys/stat.h
__STD_TYPE __DEV_T_TYPE __dev_t; // sys/types.h
#define __DEV_T_TYPE __UQUAD_TYPE; // sys/typesizes.h
So I suggest the attached patch to switch _PyLong_FromDev to
PyLong_FromUnsignedLongLong which also makes it consistent with
_Py_Dev_Converter which converts the other way with PyLong_AsUnsignedLongLong.
This change fixes the mentioned test, but another test failure is unmasked:
======================================================================
ERROR: test_makedev (test.test_posix.PosixTester)
----------------------------------------------------------------------
Traceback (most recent call last):
File "/usr/ports/lang/python311/work/Python-3.11.0a1/Lib/test/test_posix.py",
line 704, in test_makedev
self.assertEqual(posix.makedev(major, minor), dev)
^^^^^^^^^^^^^^^^^^^^^^^^^^^
OverflowError: Python int too large to convert to C int
----------------------------------------------------------------------
This problem needs couple more trivial changes, but I'm not sure how to make
them correctly (and I'm also confused by how this file relates with
clinic/posixmodule.c).
The problems are that:
- os_major_impl/os_minor_impl and os_makedev_impl are inconsistent in their
argument/return types for major/minor dev numbers: the former use `unsigned
int`, while the latter uses `int`.
- the correct type is platform dependent, for instance Linux uses `unsigned
int` and FreeBSD uses `int` (from `man makedev`).
I guess that to fix this failure one needs to add a macro/typedef for the type
for minor/major dev numbers like
#if defined(__FreeBSD__)
#define DEVICE_MAJORMINOR_T int
#else
#define DEVICE_MAJORMINOR_T unsigned int
#endif
and use it in the named functions:
static DEVICE_MAJORMINOR_T os_major_impl(PyObject *module, dev_t device)
static DEVICE_MAJORMINOR_T os_minor_impl(PyObject *module, dev_t device)
static dev_t os_makedev_impl(PyObject *module, DEVICE_MAJORMINOR_T major,
DEVICE_MAJORMINOR_T minor)
----------
components: Extension Modules, FreeBSD
files: posixmodule.c.patch
keywords: patch
messages: 406030
nosy: AMDmi3, koobs
priority: normal
severity: normal
status: open
title: Fix types for dev_t processing in posix module
type: behavior
versions: Python 3.10, Python 3.11, Python 3.6, Python 3.7, Python 3.8, Python
3.9
Added file: https://bugs.python.org/file50433/posixmodule.c.patch
_______________________________________
Python tracker <[email protected]>
<https://bugs.python.org/issue45767>
_______________________________________
_______________________________________________
Python-bugs-list mailing list
Unsubscribe:
https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com