|
|
aa419c5 |
From: Liviu Chircu <liviu@opensips.org>
|
|
|
aa419c5 |
Date: Fri, 12 Feb 2016 17:12:57 +0200
|
|
|
aa419c5 |
Subject: [PATCH] Improve qvalue parsing
|
|
|
aa419c5 |
|
|
|
aa419c5 |
* accept qvalues with no decimal digits (e.g. "1." and "0.")
|
|
|
aa419c5 |
(this removes E_Q_DEC_MISSING from error.h)
|
|
|
aa419c5 |
* improve bad qvalue error reporting
|
|
|
aa419c5 |
|
|
|
aa419c5 |
(cherry picked from commit ed60363d9d66bf230872c535e3fc0cf7f117b2c7)
|
|
|
aa419c5 |
|
|
|
aa419c5 |
Conflicts:
|
|
|
aa419c5 |
cfg.y
|
|
|
aa419c5 |
|
|
|
aa419c5 |
diff --git a/cfg.y b/cfg.y
|
|
|
aa419c5 |
index b969ce0..8b67517 100644
|
|
|
aa419c5 |
--- a/cfg.y
|
|
|
aa419c5 |
+++ b/cfg.y
|
|
|
aa419c5 |
@@ -132,7 +132,7 @@ extern int yylex();
|
|
|
aa419c5 |
static void yyerror(char* s);
|
|
|
aa419c5 |
static void yyerrorf(char* fmt, ...);
|
|
|
aa419c5 |
static char* tmp;
|
|
|
aa419c5 |
-static int i_tmp;
|
|
|
aa419c5 |
+static int i_tmp, rc;
|
|
|
aa419c5 |
static void* cmd_tmp;
|
|
|
aa419c5 |
static struct socket_id* lst_tmp;
|
|
|
aa419c5 |
static int rt; /* Type of route block for find_export */
|
|
|
aa419c5 |
@@ -2751,13 +2751,18 @@ cmd: FORWARD LPAREN STRING RPAREN { mk_action2( $$, FORWARD_T,
|
|
|
aa419c5 |
| STRIP error { $$=0; yyerror("missing '(' or ')' ?"); }
|
|
|
aa419c5 |
| STRIP LPAREN error RPAREN { $$=0; yyerror("bad argument, "
|
|
|
aa419c5 |
"number expected"); }
|
|
|
aa419c5 |
- | APPEND_BRANCH LPAREN STRING COMMA STRING RPAREN {
|
|
|
aa419c5 |
- { qvalue_t q;
|
|
|
aa419c5 |
- if (str2q(&q, $5, strlen($5)) < 0) {
|
|
|
aa419c5 |
- yyerror("bad argument, q value expected");
|
|
|
aa419c5 |
- }
|
|
|
aa419c5 |
+ | APPEND_BRANCH LPAREN STRING COMMA STRING RPAREN {
|
|
|
aa419c5 |
+ {
|
|
|
aa419c5 |
+ qvalue_t q;
|
|
|
aa419c5 |
+
|
|
|
aa419c5 |
+ rc = str2q(&q, $5, strlen($5));
|
|
|
aa419c5 |
+ if (rc < 0)
|
|
|
aa419c5 |
+ yyerrorf("bad qvalue (%.*s): %s",
|
|
|
aa419c5 |
+ strlen($5), $5, qverr2str(rc));
|
|
|
aa419c5 |
+
|
|
|
aa419c5 |
mk_action2( $$, APPEND_BRANCH_T, STR_ST, NUMBER_ST, $3,
|
|
|
aa419c5 |
- (void *)(long)q); }
|
|
|
aa419c5 |
+ (void *)(long)q);
|
|
|
aa419c5 |
+ }
|
|
|
aa419c5 |
}
|
|
|
aa419c5 |
| APPEND_BRANCH LPAREN STRING RPAREN { mk_action2( $$, APPEND_BRANCH_T,
|
|
|
aa419c5 |
STR_ST, NUMBER_ST, $3, (void *)Q_UNSPECIFIED) ; }
|
|
|
aa419c5 |
diff --git a/error.c b/error.c
|
|
|
aa419c5 |
index 9042be3..715863b 100644
|
|
|
aa419c5 |
--- a/error.c
|
|
|
aa419c5 |
+++ b/error.c
|
|
|
aa419c5 |
@@ -105,10 +105,6 @@ int err2reason_phrase(
|
|
|
aa419c5 |
error_txt="q parameter too big";
|
|
|
aa419c5 |
*sip_error=-E_BAD_REQ;
|
|
|
aa419c5 |
break;
|
|
|
aa419c5 |
- case E_Q_DEC_MISSING:
|
|
|
aa419c5 |
- error_txt="Decimal part missing in q";
|
|
|
aa419c5 |
- *sip_error=-E_BAD_REQ;
|
|
|
aa419c5 |
- break;
|
|
|
aa419c5 |
case E_NO_DESTINATION:
|
|
|
aa419c5 |
error_txt="No destination available";
|
|
|
aa419c5 |
*sip_error=-E_BAD_SERVER;
|
|
|
aa419c5 |
diff --git a/error.h b/error.h
|
|
|
aa419c5 |
index 87854ca..8e6f6a9 100644
|
|
|
aa419c5 |
--- a/error.h
|
|
|
aa419c5 |
+++ b/error.h
|
|
|
aa419c5 |
@@ -46,8 +46,7 @@
|
|
|
aa419c5 |
#define E_Q_INV_CHAR -15 /*!< Invalid character in q */
|
|
|
aa419c5 |
#define E_Q_EMPTY -16 /*!< Empty q */
|
|
|
aa419c5 |
#define E_Q_TOO_BIG -17 /*!< q too big (> 1) */
|
|
|
aa419c5 |
-#define E_Q_DEC_MISSING -18 /*!< Decimal part missing */
|
|
|
aa419c5 |
-#define E_NO_DESTINATION -19 /*!< No available destination */
|
|
|
aa419c5 |
+#define E_NO_DESTINATION -18 /*!< No available destination */
|
|
|
aa419c5 |
|
|
|
aa419c5 |
/* opensips specific error codes */
|
|
|
aa419c5 |
#define E_IP_BLOCKED -473 /*!< destination filtered */
|
|
|
aa419c5 |
diff --git a/modules/registrar/sip_msg.c b/modules/registrar/sip_msg.c
|
|
|
aa419c5 |
index 28ad6bb..e5d895d 100644
|
|
|
aa419c5 |
--- a/modules/registrar/sip_msg.c
|
|
|
aa419c5 |
+++ b/modules/registrar/sip_msg.c
|
|
|
aa419c5 |
@@ -281,12 +281,16 @@ void calc_contact_expires(struct sip_msg* _m, param_t* _ep, int* _e, struct save
|
|
|
aa419c5 |
*/
|
|
|
aa419c5 |
int calc_contact_q(param_t* _q, qvalue_t* _r)
|
|
|
aa419c5 |
{
|
|
|
aa419c5 |
+ int rc;
|
|
|
aa419c5 |
+
|
|
|
aa419c5 |
if (!_q || (_q->body.len == 0)) {
|
|
|
aa419c5 |
*_r = default_q;
|
|
|
aa419c5 |
} else {
|
|
|
aa419c5 |
- if (str2q(_r, _q->body.s, _q->body.len) < 0) {
|
|
|
aa419c5 |
+ rc = str2q(_r, _q->body.s, _q->body.len);
|
|
|
aa419c5 |
+ if (rc < 0) {
|
|
|
aa419c5 |
rerrno = R_INV_Q; /* Invalid q parameter */
|
|
|
aa419c5 |
- LM_ERR("invalid q parameter\n");
|
|
|
aa419c5 |
+ LM_ERR("invalid qvalue (%.*s): %s\n",
|
|
|
aa419c5 |
+ _q->body.len, _q->body.s, qverr2str(rc));
|
|
|
aa419c5 |
return -1;
|
|
|
aa419c5 |
}
|
|
|
aa419c5 |
}
|
|
|
aa419c5 |
diff --git a/modules/uac_redirect/rd_funcs.c b/modules/uac_redirect/rd_funcs.c
|
|
|
aa419c5 |
index ef6a923..329f2cb 100644
|
|
|
aa419c5 |
--- a/modules/uac_redirect/rd_funcs.c
|
|
|
aa419c5 |
+++ b/modules/uac_redirect/rd_funcs.c
|
|
|
aa419c5 |
@@ -106,7 +106,7 @@ static void sort_contacts(contact_t *ct_list, str *ct_array,
|
|
|
aa419c5 |
{
|
|
|
aa419c5 |
param_t *q_para;
|
|
|
aa419c5 |
qvalue_t q;
|
|
|
aa419c5 |
- int i,j;
|
|
|
aa419c5 |
+ int i, j, rc;
|
|
|
aa419c5 |
char backup;
|
|
|
aa419c5 |
|
|
|
aa419c5 |
for( ; ct_list ; ct_list = ct_list->next ) {
|
|
|
aa419c5 |
@@ -123,8 +123,10 @@ static void sort_contacts(contact_t *ct_list, str *ct_array,
|
|
|
aa419c5 |
if (q_para==0 || q_para->body.len==0) {
|
|
|
aa419c5 |
q = DEFAULT_Q_VALUE;
|
|
|
aa419c5 |
} else {
|
|
|
aa419c5 |
- if (str2q( &q, q_para->body.s, q_para->body.len)!=0) {
|
|
|
aa419c5 |
- LM_ERR("invalid q param\n");
|
|
|
aa419c5 |
+ rc = str2q( &q, q_para->body.s, q_para->body.len);
|
|
|
aa419c5 |
+ if (rc != 0) {
|
|
|
aa419c5 |
+ LM_ERR("invalid qvalue (%.*s): %s\n",
|
|
|
aa419c5 |
+ q_para->body.len, q_para->body.s, qverr2str(rc));
|
|
|
aa419c5 |
/* skip this contact */
|
|
|
aa419c5 |
continue;
|
|
|
aa419c5 |
}
|
|
|
aa419c5 |
diff --git a/qvalue.c b/qvalue.c
|
|
|
aa419c5 |
index 5cd2cd9..34029f3 100644
|
|
|
aa419c5 |
--- a/qvalue.c
|
|
|
aa419c5 |
+++ b/qvalue.c
|
|
|
aa419c5 |
@@ -75,6 +75,7 @@ int str2q(qvalue_t* q, char* s, int len)
|
|
|
aa419c5 |
break;
|
|
|
aa419c5 |
|
|
|
aa419c5 |
case '.':
|
|
|
aa419c5 |
+ *q = 0;
|
|
|
aa419c5 |
state = ST_0_PT;
|
|
|
aa419c5 |
break;
|
|
|
aa419c5 |
|
|
|
aa419c5 |
@@ -167,15 +168,8 @@ int str2q(qvalue_t* q, char* s, int len)
|
|
|
aa419c5 |
}
|
|
|
aa419c5 |
}
|
|
|
aa419c5 |
|
|
|
aa419c5 |
- switch(state) {
|
|
|
aa419c5 |
- case ST_START:
|
|
|
aa419c5 |
+ if (state == ST_START)
|
|
|
aa419c5 |
return E_Q_EMPTY;
|
|
|
aa419c5 |
|
|
|
aa419c5 |
- case ST_0_PT:
|
|
|
aa419c5 |
- case ST_1_PT:
|
|
|
aa419c5 |
- return E_Q_DEC_MISSING;
|
|
|
aa419c5 |
-
|
|
|
aa419c5 |
- default:
|
|
|
aa419c5 |
- return 0;
|
|
|
aa419c5 |
- }
|
|
|
aa419c5 |
+ return 0;
|
|
|
aa419c5 |
}
|
|
|
aa419c5 |
diff --git a/qvalue.h b/qvalue.h
|
|
|
aa419c5 |
index 96aa81f..717844c 100644
|
|
|
aa419c5 |
--- a/qvalue.h
|
|
|
aa419c5 |
+++ b/qvalue.h
|
|
|
aa419c5 |
@@ -76,6 +76,10 @@ typedef int qvalue_t;
|
|
|
aa419c5 |
#define Q_PREFIX "0."
|
|
|
aa419c5 |
#define Q_PREFIX_LEN (sizeof(Q_PREFIX) - 1)
|
|
|
aa419c5 |
|
|
|
aa419c5 |
+#define qverr2str(rc) \
|
|
|
aa419c5 |
+ (rc == E_Q_INV_CHAR ? "bad characters" : \
|
|
|
aa419c5 |
+ rc == E_Q_EMPTY ? "empty value" : \
|
|
|
aa419c5 |
+ rc == E_Q_TOO_BIG ? "max value is 1.0" : "bad qvalue")
|
|
|
aa419c5 |
|
|
|
aa419c5 |
|
|
|
aa419c5 |
/*! \brief
|