错误现象

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相关推荐

  1. SpringMVC中文件上传中 servletFileUpload解析为空

    SpringMVC中servletFileUpload解析 记录下bug,在网上看了很多都没能,现在已解决,希望对同样遇到此问题的的人一个帮助. 以下代码中SpringMVC中servletFileU ...

  2. 记一次定位解决SpringBoot中内嵌Tomcat的Bug问题

    你知道的越多,不知道的就越多,业余的像一棵小草! 你来,我们一起精进!你不来,我和你的竞争对手一起精进! 编辑:业余草 segmentfault.com/a/1190000038760707 推荐:h ...

  3. js中hover事件时候的BUG以及解决方法

    js中hover事件时候的BUG以及解决方法 参考文章: (1)js中hover事件时候的BUG以及解决方法 (2)https://www.cnblogs.com/mmykdbc/p/7464050. ...

  4. 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 ...

  5. JAVA方法调用中的解析与分派

    JAVA方法调用中的解析与分派 本文算是<深入理解JVM>的读书笔记,参考书中的相关代码示例,从字节码指令角度看看解析与分派的区别. 方法调用,其实就是要回答一个问题:JVM在执行一个方法 ...

  6. Oracle中SQL解析的流程

    Oracle中SQL解析的主要流程: 我们说的游标概念比较复杂,它可以是客户端程序中的游标,服务进程中的私有游标,以及服务器端共享池里的共享游标.假设一个游标被打开了,一般来说它的共享游标信息(包括执 ...

  7. iOS中XML解析汇总

    在时间上TBXML占优,libxml2支持了边下载边解析. 来源:http://www.codeios.com/forum.php?mod=viewthread&tid=9880&hi ...

  8. Android中怎获取json,Android应用中如何解析获取的json数据

    Android应用中如何解析获取的json数据 发布时间:2020-11-24 17:10:08 来源:亿速云 阅读:107 作者:Leah 这篇文章将为大家详细讲解有关Android应用中如何解析获 ...

  9. 关于VC++6.0中getline函数的一个bug

    关于VC++6.0中getline函数的一个bug 最近在调试程序时,发现getline函数在VC++6.0和其他编译器上运行结果不一样,比如有如下这段程序: #include <iostrea ...

最新文章

  1. BERT大火却不懂Transformer?读这一篇就够了 重点 命名实体识别
  2. 升级BIOS解决DELL R730XD虚拟机死机问题
  3. win10系统下安装Navicat for MySql 连接出现错误解决方法
  4. 使用百度UEditor
  5. HUE 提交Schedule 时区问题
  6. safari浏览器_吹爆苹果自带浏览器Safari,没有比它更贴心的浏览器了!!
  7. Codeforces | CF1029F 【Multicolored Markers】
  8. IPSEC 003 ---- IPSEC携手IKE,珠联璧合显神威
  9. 135 、137、139端口等主要用途
  10. 时间管理——永远做重要不紧急的事情
  11. Go语言在大数据时代应用前景
  12. “粤省事”春运专区上线 31项服务让回家更便捷
  13. 乌尔都语简介和Unicode由来
  14. html基础教学ppt,HTML5基础培训ppt课件
  15. 用Python计算北京地铁的两站间最短换乘路线
  16. 新浪短网址生成java_新浪短网址(T.cn)/腾讯短链接(Url.cn)在线生成以及API接口申请的教程...
  17. Luogu P1850换教室【期望dp】By cellur925
  18. Qt 添加第三方字体库
  19. json spirit_Spirit App:Web实时轻松动画
  20. java农业银行面试题

热门文章

  1. SLAM综述:激光雷达与视觉SLAM
  2. Drug Discovery Today | 频繁命中化合物机制探究:PAINS规则的局限性
  3. Nature | 有机合成的数字化
  4. 第二十八课.AlphaGo实例分析
  5. Linux5-bash基础特性之命令历史
  6. 技术贴 | MetaboAnalyst 4.0,代谢组学研究利器的升级
  7. 功能基因多样性研究概述
  8. Microbiome:HiSeq平台16S扩增子超高通量测序文库构建方法
  9. python使用openCV加载图像、并将BGR格式转换成HSV格式、定义HSV格式中需要分离颜色的掩码(掩模)区间(mask)、并使用mask信息进行颜色分离、BGR格式的图像转化为RGB、并可视化
  10. R语言Apriori算法关联规则挖掘:使用interestMeasure函数评估挖掘到的规则(包括覆盖率(coverage)和FishersExactTest)、置信度最高的五条规则(top five