structmember.c 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342
  1. /* Map C struct members to Python object attributes */
  2. #include "Python.h"
  3. #include "structmember.h" // PyMemberDef
  4. #include "pycore_abstract.h" // _PyNumber_Index()
  5. #include "pycore_long.h" // _PyLong_IsNegative()
  6. PyObject *
  7. PyMember_GetOne(const char *obj_addr, PyMemberDef *l)
  8. {
  9. PyObject *v;
  10. if (l->flags & Py_RELATIVE_OFFSET) {
  11. PyErr_SetString(
  12. PyExc_SystemError,
  13. "PyMember_GetOne used with Py_RELATIVE_OFFSET");
  14. return NULL;
  15. }
  16. const char* addr = obj_addr + l->offset;
  17. switch (l->type) {
  18. case T_BOOL:
  19. v = PyBool_FromLong(*(char*)addr);
  20. break;
  21. case T_BYTE:
  22. v = PyLong_FromLong(*(char*)addr);
  23. break;
  24. case T_UBYTE:
  25. v = PyLong_FromUnsignedLong(*(unsigned char*)addr);
  26. break;
  27. case T_SHORT:
  28. v = PyLong_FromLong(*(short*)addr);
  29. break;
  30. case T_USHORT:
  31. v = PyLong_FromUnsignedLong(*(unsigned short*)addr);
  32. break;
  33. case T_INT:
  34. v = PyLong_FromLong(*(int*)addr);
  35. break;
  36. case T_UINT:
  37. v = PyLong_FromUnsignedLong(*(unsigned int*)addr);
  38. break;
  39. case T_LONG:
  40. v = PyLong_FromLong(*(long*)addr);
  41. break;
  42. case T_ULONG:
  43. v = PyLong_FromUnsignedLong(*(unsigned long*)addr);
  44. break;
  45. case T_PYSSIZET:
  46. v = PyLong_FromSsize_t(*(Py_ssize_t*)addr);
  47. break;
  48. case T_FLOAT:
  49. v = PyFloat_FromDouble((double)*(float*)addr);
  50. break;
  51. case T_DOUBLE:
  52. v = PyFloat_FromDouble(*(double*)addr);
  53. break;
  54. case T_STRING:
  55. if (*(char**)addr == NULL) {
  56. v = Py_NewRef(Py_None);
  57. }
  58. else
  59. v = PyUnicode_FromString(*(char**)addr);
  60. break;
  61. case T_STRING_INPLACE:
  62. v = PyUnicode_FromString((char*)addr);
  63. break;
  64. case T_CHAR:
  65. v = PyUnicode_FromStringAndSize((char*)addr, 1);
  66. break;
  67. case T_OBJECT:
  68. v = *(PyObject **)addr;
  69. if (v == NULL)
  70. v = Py_None;
  71. Py_INCREF(v);
  72. break;
  73. case T_OBJECT_EX:
  74. v = *(PyObject **)addr;
  75. if (v == NULL) {
  76. PyObject *obj = (PyObject *)obj_addr;
  77. PyTypeObject *tp = Py_TYPE(obj);
  78. PyErr_Format(PyExc_AttributeError,
  79. "'%.200s' object has no attribute '%s'",
  80. tp->tp_name, l->name);
  81. }
  82. Py_XINCREF(v);
  83. break;
  84. case T_LONGLONG:
  85. v = PyLong_FromLongLong(*(long long *)addr);
  86. break;
  87. case T_ULONGLONG:
  88. v = PyLong_FromUnsignedLongLong(*(unsigned long long *)addr);
  89. break;
  90. case T_NONE:
  91. v = Py_NewRef(Py_None);
  92. break;
  93. default:
  94. PyErr_SetString(PyExc_SystemError, "bad memberdescr type");
  95. v = NULL;
  96. }
  97. return v;
  98. }
  99. #define WARN(msg) \
  100. do { \
  101. if (PyErr_WarnEx(PyExc_RuntimeWarning, msg, 1) < 0) \
  102. return -1; \
  103. } while (0)
  104. int
  105. PyMember_SetOne(char *addr, PyMemberDef *l, PyObject *v)
  106. {
  107. PyObject *oldv;
  108. if (l->flags & Py_RELATIVE_OFFSET) {
  109. PyErr_SetString(
  110. PyExc_SystemError,
  111. "PyMember_SetOne used with Py_RELATIVE_OFFSET");
  112. return -1;
  113. }
  114. addr += l->offset;
  115. if ((l->flags & READONLY))
  116. {
  117. PyErr_SetString(PyExc_AttributeError, "readonly attribute");
  118. return -1;
  119. }
  120. if (v == NULL) {
  121. if (l->type == T_OBJECT_EX) {
  122. /* Check if the attribute is set. */
  123. if (*(PyObject **)addr == NULL) {
  124. PyErr_SetString(PyExc_AttributeError, l->name);
  125. return -1;
  126. }
  127. }
  128. else if (l->type != T_OBJECT) {
  129. PyErr_SetString(PyExc_TypeError,
  130. "can't delete numeric/char attribute");
  131. return -1;
  132. }
  133. }
  134. switch (l->type) {
  135. case T_BOOL:{
  136. if (!PyBool_Check(v)) {
  137. PyErr_SetString(PyExc_TypeError,
  138. "attribute value type must be bool");
  139. return -1;
  140. }
  141. if (v == Py_True)
  142. *(char*)addr = (char) 1;
  143. else
  144. *(char*)addr = (char) 0;
  145. break;
  146. }
  147. case T_BYTE:{
  148. long long_val = PyLong_AsLong(v);
  149. if ((long_val == -1) && PyErr_Occurred())
  150. return -1;
  151. *(char*)addr = (char)long_val;
  152. /* XXX: For compatibility, only warn about truncations
  153. for now. */
  154. if ((long_val > CHAR_MAX) || (long_val < CHAR_MIN))
  155. WARN("Truncation of value to char");
  156. break;
  157. }
  158. case T_UBYTE:{
  159. long long_val = PyLong_AsLong(v);
  160. if ((long_val == -1) && PyErr_Occurred())
  161. return -1;
  162. *(unsigned char*)addr = (unsigned char)long_val;
  163. if ((long_val > UCHAR_MAX) || (long_val < 0))
  164. WARN("Truncation of value to unsigned char");
  165. break;
  166. }
  167. case T_SHORT:{
  168. long long_val = PyLong_AsLong(v);
  169. if ((long_val == -1) && PyErr_Occurred())
  170. return -1;
  171. *(short*)addr = (short)long_val;
  172. if ((long_val > SHRT_MAX) || (long_val < SHRT_MIN))
  173. WARN("Truncation of value to short");
  174. break;
  175. }
  176. case T_USHORT:{
  177. long long_val = PyLong_AsLong(v);
  178. if ((long_val == -1) && PyErr_Occurred())
  179. return -1;
  180. *(unsigned short*)addr = (unsigned short)long_val;
  181. if ((long_val > USHRT_MAX) || (long_val < 0))
  182. WARN("Truncation of value to unsigned short");
  183. break;
  184. }
  185. case T_INT:{
  186. long long_val = PyLong_AsLong(v);
  187. if ((long_val == -1) && PyErr_Occurred())
  188. return -1;
  189. *(int *)addr = (int)long_val;
  190. if ((long_val > INT_MAX) || (long_val < INT_MIN))
  191. WARN("Truncation of value to int");
  192. break;
  193. }
  194. case T_UINT: {
  195. /* XXX: For compatibility, accept negative int values
  196. as well. */
  197. v = _PyNumber_Index(v);
  198. if (v == NULL) {
  199. return -1;
  200. }
  201. if (_PyLong_IsNegative((PyLongObject *)v)) {
  202. long long_val = PyLong_AsLong(v);
  203. Py_DECREF(v);
  204. if (long_val == -1 && PyErr_Occurred()) {
  205. return -1;
  206. }
  207. *(unsigned int *)addr = (unsigned int)(unsigned long)long_val;
  208. WARN("Writing negative value into unsigned field");
  209. }
  210. else {
  211. unsigned long ulong_val = PyLong_AsUnsignedLong(v);
  212. Py_DECREF(v);
  213. if (ulong_val == (unsigned long)-1 && PyErr_Occurred()) {
  214. return -1;
  215. }
  216. *(unsigned int*)addr = (unsigned int)ulong_val;
  217. if (ulong_val > UINT_MAX) {
  218. WARN("Truncation of value to unsigned int");
  219. }
  220. }
  221. break;
  222. }
  223. case T_LONG:{
  224. *(long*)addr = PyLong_AsLong(v);
  225. if ((*(long*)addr == -1) && PyErr_Occurred())
  226. return -1;
  227. break;
  228. }
  229. case T_ULONG: {
  230. /* XXX: For compatibility, accept negative int values
  231. as well. */
  232. v = _PyNumber_Index(v);
  233. if (v == NULL) {
  234. return -1;
  235. }
  236. if (_PyLong_IsNegative((PyLongObject *)v)) {
  237. long long_val = PyLong_AsLong(v);
  238. Py_DECREF(v);
  239. if (long_val == -1 && PyErr_Occurred()) {
  240. return -1;
  241. }
  242. *(unsigned long *)addr = (unsigned long)long_val;
  243. WARN("Writing negative value into unsigned field");
  244. }
  245. else {
  246. unsigned long ulong_val = PyLong_AsUnsignedLong(v);
  247. Py_DECREF(v);
  248. if (ulong_val == (unsigned long)-1 && PyErr_Occurred()) {
  249. return -1;
  250. }
  251. *(unsigned long*)addr = ulong_val;
  252. }
  253. break;
  254. }
  255. case T_PYSSIZET:{
  256. *(Py_ssize_t*)addr = PyLong_AsSsize_t(v);
  257. if ((*(Py_ssize_t*)addr == (Py_ssize_t)-1)
  258. && PyErr_Occurred())
  259. return -1;
  260. break;
  261. }
  262. case T_FLOAT:{
  263. double double_val = PyFloat_AsDouble(v);
  264. if ((double_val == -1) && PyErr_Occurred())
  265. return -1;
  266. *(float*)addr = (float)double_val;
  267. break;
  268. }
  269. case T_DOUBLE:
  270. *(double*)addr = PyFloat_AsDouble(v);
  271. if ((*(double*)addr == -1) && PyErr_Occurred())
  272. return -1;
  273. break;
  274. case T_OBJECT:
  275. case T_OBJECT_EX:
  276. oldv = *(PyObject **)addr;
  277. *(PyObject **)addr = Py_XNewRef(v);
  278. Py_XDECREF(oldv);
  279. break;
  280. case T_CHAR: {
  281. const char *string;
  282. Py_ssize_t len;
  283. string = PyUnicode_AsUTF8AndSize(v, &len);
  284. if (string == NULL || len != 1) {
  285. PyErr_BadArgument();
  286. return -1;
  287. }
  288. *(char*)addr = string[0];
  289. break;
  290. }
  291. case T_STRING:
  292. case T_STRING_INPLACE:
  293. PyErr_SetString(PyExc_TypeError, "readonly attribute");
  294. return -1;
  295. case T_LONGLONG:{
  296. long long value;
  297. *(long long*)addr = value = PyLong_AsLongLong(v);
  298. if ((value == -1) && PyErr_Occurred())
  299. return -1;
  300. break;
  301. }
  302. case Py_T_ULONGLONG: {
  303. v = _PyNumber_Index(v);
  304. if (v == NULL) {
  305. return -1;
  306. }
  307. if (_PyLong_IsNegative((PyLongObject *)v)) {
  308. long long_val = PyLong_AsLong(v);
  309. Py_DECREF(v);
  310. if (long_val == -1 && PyErr_Occurred()) {
  311. return -1;
  312. }
  313. *(unsigned long long *)addr = (unsigned long long)(long long)long_val;
  314. WARN("Writing negative value into unsigned field");
  315. }
  316. else {
  317. unsigned long long ulonglong_val = PyLong_AsUnsignedLongLong(v);
  318. Py_DECREF(v);
  319. if (ulonglong_val == (unsigned long long)-1 && PyErr_Occurred()) {
  320. return -1;
  321. }
  322. *(unsigned long long*)addr = ulonglong_val;
  323. }
  324. break;
  325. }
  326. default:
  327. PyErr_Format(PyExc_SystemError,
  328. "bad memberdescr type for %s", l->name);
  329. return -1;
  330. }
  331. return 0;
  332. }