Module: kamailio
Branch: master
Commit: 7bc82ef842316449cbebeddf594a0e2975855242
URL: https://github.com/kamailio/kamailio/commit/7bc82ef842316449cbebeddf594a0e2…
Author: Daniel-Constantin Mierla <miconda(a)gmail.com>
Committer: Daniel-Constantin Mierla <miconda(a)gmail.com>
Date: 2018-07-09T10:20:42+02:00
core: cfg struct - pack structures that use a dynamic array at the end
- compiler padding to alling fields results in wrong offset for last
field which is computed as `sizeof(struct) - 1
- GH #1583
---
Modified: src/core/cfg/cfg_struct.h
---
Diff: https://github.com/kamailio/kamailio/commit/7bc82ef842316449cbebeddf594a0e2…
Patch: https://github.com/kamailio/kamailio/commit/7bc82ef842316449cbebeddf594a0e2…
---
diff --git a/src/core/cfg/cfg_struct.h b/src/core/cfg/cfg_struct.h
index 6436eed677..e03024e700 100644
--- a/src/core/cfg/cfg_struct.h
+++ b/src/core/cfg/cfg_struct.h
@@ -40,22 +40,24 @@
* When the config is shmzied, these variables are combined in
* an array.
*/
+#pragma pack(push, 1)
typedef struct _cfg_add_var {
struct _cfg_add_var *next;
unsigned int type; /*!< type == 0 is also valid, it indicates that the group
must be created with the default values */
+ unsigned int group_id; /*!< Id of the group instance */
union {
char *ch;
str s;
int i;
} val;
- unsigned int group_id; /*!< Id of the group instance */
int name_len; /*!< Name of the variable. The variable may not be known,
for example the additional group value is set in the script
before the cfg group is declared. Hence, the pointer cannot
be stored here. */
char name[1];
} cfg_add_var_t;
+#pragma pack(pop)
/*! \brief structure used for variable - pointer mapping */
typedef struct _cfg_mapping {
@@ -72,6 +74,7 @@ typedef struct _cfg_mapping {
enum { CFG_GROUP_UNKNOWN = 0, CFG_GROUP_DYNAMIC, CFG_GROUP_STATIC };
/*! \brief linked list of registered groups */
+#pragma pack(push, 1)
typedef struct _cfg_group {
int num; /*!< number of variables within the group */
cfg_mapping_t *mapping; /*!< describes the mapping betweeen
@@ -103,9 +106,11 @@ typedef struct _cfg_group {
int name_len;
char name[1];
} cfg_group_t;
+#pragma pack(pop)
/*! \brief One instance of the cfg group variables which stores
* the additional values. These values can overwrite the default values. */
+#pragma pack(push, 1)
typedef struct _cfg_group_inst {
unsigned int id; /*!< identifier of the group instance */
unsigned int set[CFG_MAX_VAR_NUM/(sizeof(int)*8)];
@@ -114,6 +119,7 @@ typedef struct _cfg_group_inst {
then the default value is used, and copied into this instance. */
unsigned char vars[1]; /*!< block for the values */
} cfg_group_inst_t;
+#pragma pack(pop)
/*! \brief Meta-data which is stored before each variable group
* within the blob. This structure is used to handle the multivalue
@@ -125,6 +131,7 @@ typedef struct _cfg_group_meta {
} cfg_group_meta_t;
/*! \brief single memoy block that contains all the cfg values */
+#pragma pack(push, 1)
typedef struct _cfg_block {
atomic_t refcnt; /*!< reference counter,
the block is automatically deleted
@@ -132,6 +139,7 @@ typedef struct _cfg_block {
int _pad; /*!< force 8 byte alignment */
unsigned char vars[1]; /*!< blob that contains the values */
} cfg_block_t;
+#pragma pack(pop)
/*! \brief Linked list of per-child process callbacks.
* Each child process has a local pointer, and executes the callbacks
Hello,
starting here a discussion about an issue with the database API and
signed/unsigned number type to see how to address it.
So far, the database API supported only signed types for numbers,
respectively DB1_INT (int in c) and DB1_BIGINT (long long in c).
However, many database table columns are defined as UNSIGNED INT or
UNSIGNED BIGINT. The database connector modules are mapping UNSIGED
values retrieved from database over signed fields in DB API structure.
The other way around is done as well: signed values are the inserted in
the unsigned columns.
There is no issue if the value in C is a positive number, however, if
the value goes over MAX_UINT/2 (over 2147483647), it becomes negative
and inserting the value in database results in an exception and 0 being
stored instead.
So far, I guess the issue was rarely exposed, if at all, because no
report on it, even these data types for DB1 are since the SER project
was started in 2001. As I looked at database definition schema, most of
unsigned columns are for internal flags or ids (e.g., lcr_id), where I
guess no large values were used or needed so far.
However, it can bite at any time and needs to be addressed. So far, two
solutions come in mind:
1) drop using UNSIGNED INT for those db columns, use only INT and do
unsigned cast in the C code when reading and cast to int when writing.
2) update the db connector modules to support unsigned types -- I added
support for them in DB API, but each db_* module has to be updated. The
also each module that uses UNSIGNED DB columns must be updated
1) should be simpler, 2) more work but better in long term
Any other ideas? Which of the options you prefer to go for?
Not to forget: somehow related, probably we have to switch from int to
long for PV number values, otherwise timestamp variables can go negative
once unix timestamp approaches MAX_UINT/2 (still plenty of time, but
should not be delayed for long ...).
Cheers,
Daniel
--
Daniel-Constantin Mierla -- www.asipto.comwww.twitter.com/miconda -- www.linkedin.com/in/miconda
Kamailio World Conference -- www.kamailioworld.com