opensips中db_default_url解析存在的bug
错误现象
22:29:55 [86] DBG:db_mysql:db_mysql_connect: opening connection: mysql://xxxx:xxxx@:gsf@1202]@10.10.10.10/opensips
22:29:55 [86] ERROR:db_mysql:db_mysql_connect: driver error(2005): Unknown MySQL server host ':gsf@1202]@10.10.10.10' (2)
22:29:55 [86] ERROR:db_mysql:db_mysql_new_connection: initial connect failed
22:29:55 [86] ERROR:core:db_do_init: could not add connection to the pool
22:29:55 [86] ERROR:uri:mod_init: Could not connect to database
原因分析
opensips中的db_default_url的解析是自己实现的,2.x源码在db/db_id.c
如果你的密码存在特殊字符,如@,!等,这个解析就存在bug
根据它源码的注释,它是可以通过[] 来实现转义的,
scheme://[username[:password]@]hostname[:port]/database
但是实际上功能上存在bug。
我把它的源码部分贴出来,如果遇到问题的,可以自己试着跑一下
#include <stdio.h>
#include <stdlib.h>
#include <memory.h>typedef struct __str {char* s; /**< string as char array */int len; /**< string length, not including null-termination */
} str;/** Structure representing a database ID */
struct db_id {char* scheme; /**< URL scheme */char* username; /**< Username, case sensitive */char* password; /**< Password, case sensitive */char* host; /**< Host or IP, case insensitive */unsigned short port; /**< Port number */char* database; /**< Database, case sensitive */str url; /**< Pointer to the original url> */
};unsigned short str2s(const char* s, unsigned int len, int *err)
{unsigned short ret;int i;unsigned char *limit;unsigned char *str;/*init*/str=(unsigned char*)s;ret=i=0;limit=str+len;for(;str<limit ;str++){if ( (*str <= '9' ) && (*str >= '0') ){ret=ret*10+*str-'0';i++;if (i>5) goto error_digits;}else{//error unknown chargoto error_char;}}if (err) *err=0;return ret;error_digits:printf("too many letters in [%.*s]\n", (int)len, s);if (err) *err=1;return 0;error_char:printf("unexpected char %c in %.*s\n", *str, (int)len, s);if (err) *err=1;return 0;
}static int dupl_string(char** dst, const char* begin, const char* end)
{if (*dst) free(*dst);*dst = malloc(end - begin + 1);if ((*dst) == NULL) {return -1;}memcpy(*dst, begin, end - begin);(*dst)[end - begin] = '\0';return 0;
}/*** Parse a database URL of form* scheme://[username[:password]@]hostname[:port]/database** \param id filled id struct* \param url parsed URL* \return 0 if parsing was successful and -1 otherwise*/
int parse_db_url(struct db_id* id, const str* url)
{#define SHORTEST_DB_URL "s://a/b"
#define SHORTEST_DB_URL_LEN (sizeof(SHORTEST_DB_URL) - 1)enum state {ST_SCHEME, /* Scheme part */ST_SLASH1, /* First slash */ST_SLASH2, /* Second slash */ST_USER_HOST, /* Username or hostname */ST_PASS_PORT, /* Password or port part */ST_HOST, /* Hostname part */ST_HOST6, /* Hostname part IPv6 */ST_PORT, /* Port part */ST_DB /* Database part */};enum state st;unsigned int len, i, ipv6_flag=0;const char* begin;char* prev_token = NULL;if (!id || !url || !url->s) {return -1;}len = url->len;if (len < SHORTEST_DB_URL_LEN) {return -1;}/* Initialize all attributes to 0 */memset(id, 0, sizeof(struct db_id));st = ST_SCHEME;begin = url->s;for(i = 0; i < len; i++) {switch(st) {case ST_SCHEME:switch(url->s[i]) {case ':':st = ST_SLASH1;if (dupl_string(&id->scheme, begin, url->s + i) < 0) goto err;break;}break;case ST_SLASH1:switch(url->s[i]) {case '/':st = ST_SLASH2;break;default:goto err;}break;case ST_SLASH2:switch(url->s[i]) {case '/':st = ST_USER_HOST;begin = url->s + i + 1;break;default:goto err;}break;case ST_USER_HOST:switch(url->s[i]) {case '@':st = ST_HOST;if (dupl_string(&id->username, begin, url->s + i) < 0) goto err;begin = url->s + i + 1;break;case ':':st = ST_PASS_PORT;if (dupl_string(&prev_token, begin, url->s + i) < 0) goto err;begin = url->s + i + 1;break;case '[':st = ST_HOST6;begin = url->s + i + 1;break;case '/':if (dupl_string(&id->host, begin, url->s + i) < 0) goto err;if (dupl_string(&id->database, url->s + i + 1, url->s + len) < 0) goto err;return 0;}break;case ST_PASS_PORT:switch(url->s[i]) {case '@':st = ST_HOST;id->username = prev_token; prev_token = NULL;if (dupl_string(&id->password, begin, url->s + i) < 0) goto err;begin = url->s + i + 1;break;case '/':id->host = prev_token; prev_token = NULL;id->port = str2s(begin, url->s + i - begin, 0);if (dupl_string(&id->database, url->s + i + 1, url->s + len) < 0) goto err;return 0;}break;case ST_HOST:switch(url->s[i]) {case '[':st = ST_HOST6;begin = url->s + i + 1;break;case ':':st = ST_PORT;if (dupl_string(&id->host, begin, url->s + i - ipv6_flag) < 0) goto err;begin = url->s + i + 1;break;case '/':if (dupl_string(&id->host, begin, url->s + i - ipv6_flag) < 0) goto err;if (dupl_string(&id->database, url->s + i + 1, url->s + len) < 0) goto err;return 0;}break;case ST_HOST6:switch(url->s[i]) {case ']':ipv6_flag = 1;st = ST_HOST;break;}break;case ST_PORT:switch(url->s[i]) {case '/':id->port = str2s(begin, url->s + i - begin, 0);if (dupl_string(&id->database, url->s + i + 1, url->s + len) < 0) goto err;return 0;}break;case ST_DB:break;}}if (st != ST_DB) goto err;return 0;err:if (id->scheme) free(id->scheme);if (id->username) free(id->username);if (id->password) free(id->password);if (id->host) free(id->host);if (id->database) free(id->database);if (prev_token) free(prev_token);return -1;
}int main() {struct db_id id;str url;url.s = "mysql://root:gsf1202@10.10.10.10/opensips";url.len = strlen(url.s);parse_db_url(&id, &url);printf("scheme: %s \n""usename: %s \n""password: %s \n""host : %s \n""database: %s \n""port : %d",id.scheme, id.username, id.password, id.host,id.database, id.port);return 0;
}
opensips中db_default_url解析存在的bug相关推荐
- SpringMVC中文件上传中 servletFileUpload解析为空
SpringMVC中servletFileUpload解析 记录下bug,在网上看了很多都没能,现在已解决,希望对同样遇到此问题的的人一个帮助. 以下代码中SpringMVC中servletFileU ...
- 记一次定位解决SpringBoot中内嵌Tomcat的Bug问题
你知道的越多,不知道的就越多,业余的像一棵小草! 你来,我们一起精进!你不来,我和你的竞争对手一起精进! 编辑:业余草 segmentfault.com/a/1190000038760707 推荐:h ...
- js中hover事件时候的BUG以及解决方法
js中hover事件时候的BUG以及解决方法 参考文章: (1)js中hover事件时候的BUG以及解决方法 (2)https://www.cnblogs.com/mmykdbc/p/7464050. ...
- 0.11内核rd_load@ramdisk.c中memcpy函数好像有bug
0.11内核rd_load@ramdisk.c中memcpy函数好像有bug,如: #define memcpy(dst,src,n) \ __asm__("cld;rep;movs ...
- JAVA方法调用中的解析与分派
JAVA方法调用中的解析与分派 本文算是<深入理解JVM>的读书笔记,参考书中的相关代码示例,从字节码指令角度看看解析与分派的区别. 方法调用,其实就是要回答一个问题:JVM在执行一个方法 ...
- Oracle中SQL解析的流程
Oracle中SQL解析的主要流程: 我们说的游标概念比较复杂,它可以是客户端程序中的游标,服务进程中的私有游标,以及服务器端共享池里的共享游标.假设一个游标被打开了,一般来说它的共享游标信息(包括执 ...
- iOS中XML解析汇总
在时间上TBXML占优,libxml2支持了边下载边解析. 来源:http://www.codeios.com/forum.php?mod=viewthread&tid=9880&hi ...
- Android中怎获取json,Android应用中如何解析获取的json数据
Android应用中如何解析获取的json数据 发布时间:2020-11-24 17:10:08 来源:亿速云 阅读:107 作者:Leah 这篇文章将为大家详细讲解有关Android应用中如何解析获 ...
- 关于VC++6.0中getline函数的一个bug
关于VC++6.0中getline函数的一个bug 最近在调试程序时,发现getline函数在VC++6.0和其他编译器上运行结果不一样,比如有如下这段程序: #include <iostrea ...
最新文章
- BERT大火却不懂Transformer?读这一篇就够了 重点 命名实体识别
- 升级BIOS解决DELL R730XD虚拟机死机问题
- win10系统下安装Navicat for MySql 连接出现错误解决方法
- 使用百度UEditor
- HUE 提交Schedule 时区问题
- safari浏览器_吹爆苹果自带浏览器Safari,没有比它更贴心的浏览器了!!
- Codeforces | CF1029F 【Multicolored Markers】
- IPSEC 003 ---- IPSEC携手IKE,珠联璧合显神威
- 135 、137、139端口等主要用途
- 时间管理——永远做重要不紧急的事情
- Go语言在大数据时代应用前景
- “粤省事”春运专区上线 31项服务让回家更便捷
- 乌尔都语简介和Unicode由来
- html基础教学ppt,HTML5基础培训ppt课件
- 用Python计算北京地铁的两站间最短换乘路线
- 新浪短网址生成java_新浪短网址(T.cn)/腾讯短链接(Url.cn)在线生成以及API接口申请的教程...
- Luogu P1850换教室【期望dp】By cellur925
- Qt 添加第三方字体库
- json spirit_Spirit App:Web实时轻松动画
- java农业银行面试题
热门文章
- SLAM综述:激光雷达与视觉SLAM
- Drug Discovery Today | 频繁命中化合物机制探究:PAINS规则的局限性
- Nature | 有机合成的数字化
- 第二十八课.AlphaGo实例分析
- Linux5-bash基础特性之命令历史
- 技术贴 | MetaboAnalyst 4.0,代谢组学研究利器的升级
- 功能基因多样性研究概述
- Microbiome:HiSeq平台16S扩增子超高通量测序文库构建方法
- python使用openCV加载图像、并将BGR格式转换成HSV格式、定义HSV格式中需要分离颜色的掩码(掩模)区间(mask)、并使用mask信息进行颜色分离、BGR格式的图像转化为RGB、并可视化
- R语言Apriori算法关联规则挖掘:使用interestMeasure函数评估挖掘到的规则(包括覆盖率(coverage)和FishersExactTest)、置信度最高的五条规则(top five