ARMmbed / ATParser

Parser for AT commands and similar protocols.
35 stars 27 forks source link

ATParser could not support some strings very well. #7

Open tz-arm opened 6 years ago

tz-arm commented 6 years ago

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);
}
tz-arm commented 6 years ago

Duplicated issue with https://github.com/ARMmbed/ATParser/issues/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 commented 6 years ago

@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:

Specifies the maximum number of characters to be read in the current reading operation (optional).

So, this operation is not greedy.

tz-arm commented 6 years ago

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 commented 6 years ago

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.