Open
Description
I am working to integrate a NBIoT module and found that this ATParser could not support some strings.
After debugging, I found it is caused by the poor sscanf().
For example,
_parser.recv("\"%15[^\n]\"", dev_info.imsi);
from ESP8266 driver as reference , it could work.
_parser.recv("%15[^\n]", dev_info.imsi);
with no quotes does not work well. it will return the first char in the string to imsi.
Below is a simple test code, would you help to share comments if any idea?
void verify_sscanf()
{
//Verify the AT format for esp8266 with quotes
int count = -1;
char test[] = "0\"123456789\"";
char test1[] = "0\"%*9[^\n]\"%n0";
char test2[] = "0\"1234\"";
sscanf(test2, test1, &count);
printf("\nESP8266: expect -1 - count = %d\n", count);
count = -1;
sscanf(test, test1, &count);
printf("\nESP8266: expect 12 - count = %d\n", count);
//Verify the AT format for BC95 without quotes
char test_bc95[] = "0123456789";
char test1_bc95[] = "0%*9[^\n]%n0";
char test2_bc95[] = "01234";
count = -1;
sscanf(test2_bc95, test1_bc95, &count);
printf("\nBC95: expect -1 - count = %d\n", count);
count = -1;
sscanf(test_bc95, test1_bc95, &count);
printf("\nBC95: expect 10 BUT fail- count = %d\n", count);
}
Activity
tz-arm commentedon Jul 18, 2017
Duplicated issue with #1:
Got the solution from the reference:
https://github.com/sarahmarshy/mxchip-wifi-driver/blob/at-parser-port/mxchip/MXCHIP.cpp#L165
Use _parser.recv("%[^\r]%*[\r]%*[\n]") instead of _parser.recv("%15[^\r\n]")
sarahmarshy commentedon Jul 18, 2017
@tz-arm According to this (http://www.cplusplus.com/reference/cstdio/scanf/), it looks like the 15 in that formatter is considered the "width." This is what that document says about width:
So, this operation is not greedy.
tz-arm commentedon Jul 19, 2017
I saw ESP8266 driver and PPPCellularInterface are using this "width" parameters.
Since the esp8266 use quotes in the string, it works well. but I really adapt if it is working well in PPPCellularInterface reference.
Maybe we can propose to unify all usages?
geky commentedon Jul 19, 2017
I would actually use this:
_parser.recv("%15[^\r]%*[\r]%*[\n]")
The 15 protects against buffer overflow if you accidentally end up reading corrupt data. But @sarahmarshy is right this only specifies the max. The way the ATParser calls scanf makes the match non-greedy, which is a bit counter-intuitive if you're familiar with regex, where greedy matches are the norm.
Non-greedy matching means you will need to explicitly indicate what stops the pattern, in this case the pattern
%*[\r]%*[\n]
works fine.