bpo-29753: fix merging packed bitfields in ctypes struct/union (GH-19… · python/cpython@0d7ad9f (original) (raw)

`@@ -71,6 +71,18 @@ PyCField_FromDesc(PyObject *desc, Py_ssize_t index,

`

71

71

`Py_DECREF(self);

`

72

72

`return NULL;

`

73

73

` }

`

``

74

+

``

75

`+

#ifndef MS_WIN32

`

``

76

`+

/* if we have a packed bitfield, calculate the minimum number of bytes we

`

``

77

`+

need to fit it. otherwise use the specified size. */

`

``

78

`+

if (pack && bitsize) {

`

``

79

`+

size = (bitsize - 1) / 8 + 1;

`

``

80

`+

} else

`

``

81

`+

#endif

`

``

82

`+

size = dict->size;

`

``

83

+

``

84

`+

proto = desc;

`

``

85

+

74

86

`if (bitsize /* this is a bitfield request */

`

75

87

`&& pfield_size / we have a bitfield open */

`

76

88

`#ifdef MS_WIN32

`

`@@ -87,25 +99,26 @@ PyCField_FromDesc(PyObject *desc, Py_ssize_t index,

`

87

99

` } else if (bitsize /* this is a bitfield request */

`

88

100

`&& pfield_size / we have a bitfield open */

`

89

101

`&& dict->size * 8 >= *pfield_size

`

90

``

`-

&& (*pbitofs + bitsize) <= dict->size * 8) {

`

``

102

`+

/* if this is a packed bitfield, always expand it.

`

``

103

`+

otherwise calculate if we need to expand it. */

`

``

104

`+

&& (((*pbitofs + bitsize) <= dict->size * 8) || pack)) {

`

91

105

`/* expand bit field */

`

92

106

`fieldtype = EXPAND_BITFIELD;

`

93

107

`#endif

`

94

108

` } else if (bitsize) {

`

95

109

`/* start new bitfield */

`

96

110

`fieldtype = NEW_BITFIELD;

`

97

111

`*pbitofs = 0;

`

98

``

`-

*pfield_size = dict->size * 8;

`

``

112

`+

/* use our calculated size (size) instead of type size (dict->size),

`

``

113

`+

which can be different for packed bitfields */

`

``

114

`+

*pfield_size = size * 8;

`

99

115

` } else {

`

100

116

`/* not a bit field */

`

101

117

`fieldtype = NO_BITFIELD;

`

102

118

`*pbitofs = 0;

`

103

119

`*pfield_size = 0;

`

104

120

` }

`

105

121

``

106

``

`-

size = dict->size;

`

107

``

`-

proto = desc;

`

108

``

-

109

122

`/* Field descriptors for 'c_char * n' are be scpecial cased to

`

110

123

` return a Python string instead of an Array object instance...

`

111

124

` */

`

`@@ -170,10 +183,16 @@ PyCField_FromDesc(PyObject *desc, Py_ssize_t index,

`

170

183

`break;

`

171

184

``

172

185

`case EXPAND_BITFIELD:

`

173

``

`-

*poffset += dict->size - *pfield_size/8;

`

174

``

`-

*psize += dict->size - *pfield_size/8;

`

``

186

`+

/* increase the size if it is a packed bitfield.

`

``

187

`+

EXPAND_BITFIELD should not be selected for non-packed fields if the

`

``

188

`+

current size isn't already enough. */

`

``

189

`+

if (pack)

`

``

190

`+

size = (*pbitofs + bitsize - 1) / 8 + 1;

`

``

191

+

``

192

`+

*poffset += size - *pfield_size/8;

`

``

193

`+

*psize += size - *pfield_size/8;

`

175

194

``

176

``

`-

*pfield_size = dict->size * 8;

`

``

195

`+

*pfield_size = size * 8;

`

177

196

``

178

197

`if (big_endian)

`

179

198

`self->size = (bitsize << 16) + *pfield_size - *pbitofs - bitsize;

`