最近,我在使用rtklib低成本优化版本demo5进行静态ppp解算时,发现程序读取的观测数据错误,经过反复排查后发现是程序bug引起的。
demo5_b34e rinex.c 中 decode_obsdata函数按照优先级的选取观测值部分存在问题,导致数组超界。
原函数(存在bug):
/* decode observation data ---------------------------------------------------*/
static int decode_obsdata(FILE *fp, char *buff, double ver, int mask,
sigind_t *index, obsd_t *obs)
{
sigind_t *ind;
double val[MAXOBSTYPE]={0};
uint8_t lli[MAXOBSTYPE]={0};
uint8_t std[MAXOBSTYPE]={0};
char satid[8]="";
int i,j,n,m,q,stat=1,p[MAXOBSTYPE],k[16],l[16],r[16];
trace(4,"decode_obsdata: ver=%.2f\n",ver);
if (ver>2.99) { /* ver.3 */
sprintf(satid,"%.3s",buff);
obs->sat=(uint8_t)satid2no(satid);
}
if (!obs->sat) {
trace(4,"decode_obsdata: unsupported sat sat=%s\n",satid);
stat=0;
}
else if (!(satsys(obs->sat,NULL)&mask)) {
stat=0;
}
/* read observation data fields */
switch (satsys(obs->sat,NULL)) {
case SYS_GLO: ind=index+1; break;
case SYS_GAL: ind=index+2; break;
case SYS_QZS: ind=index+3; break;
case SYS_SBS: ind=index+4; break;
case SYS_CMP: ind=index+5; break;
case SYS_IRN: ind=index+6; break;
default: ind=index ; break;
}
for (i=0,j=ver<=2.99?0:3;i<ind->n;i++,j+=16) {
if (ver<=2.99&&j>=80) { /* ver.2 */
if (!fgets(buff,MAXRNXLEN,fp)) break;
j=0;
}
if (stat) {
val[i]=str2num(buff,j,14)+ind->shift[i];
lli[i]=(uint8_t)str2num(buff,j+14,1)&3;
/* measurement std from receiver */
std[i]=(uint8_t)str2num(buff,j+15,1);
}
}
if (!stat) return 0;
for (i=0;i<NFREQ+NEXOBS;i++) {
obs->P[i]=obs->L[i]=0.0; obs->D[i]=0.0f;
obs->SNR[i]=obs->LLI[i]=obs->Lstd[i]=obs->Pstd[i]=obs->code[i]=0;
}
/* assign position in observation data */
for (i=n=m=q=0;i<ind->n;i++) {
p[i]=ind->idx[i];
if (ind->type[i]==0&&p[i]==0) k[n++]=i; /* C1? index */
if (ind->type[i]==0&&p[i]==1) l[m++]=i; /* C2? index */
if (ind->type[i]==0&&p[i]==2) r[q++]=i; /* C3? index */
}
/* if multiple codes (C1/P1,C2/P2), select higher priority */
if (n>=2) {
if (val[k[0]]==0.0&&val[k[1]]==0.0) {
p[k[0]]=-1; p[k[1]]=-1;
}
else if (val[k[0]]!=0.0&&val[k[1]]==0.0) {
p[k[0]]=0; p[k[1]]=-1;
}
else if (val[k[0]]==0.0&&val[k[1]]!=0.0) {
p[k[0]]=-1; p[k[1]]=0;
}
else if (ind->pri[k[1]]>ind->pri[k[0]]) {
p[k[1]]=0; p[k[0]]=NEXOBS<1?-1:NFREQ;
}
else {
p[k[0]]=0; p[k[1]]=NEXOBS<1?-1:NFREQ;
}
}
if (m>=2) {
if (val[l[0]]==0.0&&val[l[1]]==0.0) {
p[l[0]]=-1; p[l[1]]=-1;
}
else if (val[l[0]]!=0.0&&val[l[1]]==0.0) {
p[l[0]]=1; p[l[1]]=-1;
}
else if (val[l[0]]==0.0&&val[l[1]]!=0.0) {
p[l[0]]=-1; p[l[1]]=1;
}
else if (ind->pri[l[1]]>ind->pri[l[0]]) {
p[l[1]]=1; p[l[0]]=NEXOBS<2?-1:NFREQ+1;
}
else {
p[l[0]]=1; p[l[1]]=NEXOBS<2?-1:NFREQ+1;
}
}
if (q>=2) {
if (val[r[0]]==0.0&&val[r[1]]==0.0) {
p[r[0]]=-1; p[r[1]]=-1;
}
else if (val[r[0]]!=0.0&&val[r[1]]==0.0) {
p[l[0]]=1; p[l[1]]=-1;
}
else if (val[r[0]]==0.0&&val[r[1]]!=0.0) {
p[r[0]]=-1; p[r[1]]=1;
}
else if (ind->pri[r[1]]>ind->pri[r[0]]) {
p[r[1]]=1; p[r[0]]=NEXOBS<3?-1:NFREQ+2;
}
else {
p[r[0]]=1; p[r[1]]=NEXOBS<3?-1:NFREQ+2;
}
}
/* save observation data */
for (i=0;i<ind->n;i++) {
if (p[i]<0||(val[i]==0.0&&lli[i]==0)) continue;
switch (ind->type[i]) {
case 0: obs->P[p[i]]=val[i];
obs->code[p[i]]=ind->code[i];
obs->Pstd[p[i]]=std[i]>0?std[i]:1;
break;
case 1: obs->L[p[i]]=val[i];
obs->LLI[p[i]]=lli[i];
obs->Lstd[p[i]]=std[i]>0?std[i]:1;
break;
case 2: obs->D[p[i]]=(float)val[i]; break;
case 3: obs->SNR[p[i]]=(uint16_t)(val[i]/SNR_UNIT+0.5); break;
}
}
trace(4,"decode_obsdata: time=%s sat=%2d\n",time_str(obs->time,0),obs->sat);
return 1;
}
修复后函数:
/* decode observation data ---------------------------------------------------*/
static int decode_obsdata(FILE *fp, char *buff, double ver, int mask,
sigind_t *index, obsd_t *obs)
{
sigind_t *ind;
double val[MAXOBSTYPE]={0};
uint8_t lli[MAXOBSTYPE]={0};
uint8_t std[MAXOBSTYPE]={0};
char satid[8]="";
int i,j,n,m,q,stat=1,ifrq[MAXOBSTYPE],k[16],l[16],r[16];
int f, iobs[NFREQ][MAXOBSTYPE / 4], nobs[NFREQ], maxpri, imax;
trace(4,"decode_obsdata: ver=%.2f\n",ver);
if (ver>2.99) { /* ver.3 */
sprintf(satid,"%.3s",buff);
obs->sat=(uint8_t)satid2no(satid);
}
if (!obs->sat) {
trace(4,"decode_obsdata: unsupported sat sat=%s\n",satid);
stat=0;
}
else if (!(satsys(obs->sat,NULL)&mask)) {
stat=0;
}
/* read observation data fields */
switch (satsys(obs->sat,NULL)) {
case SYS_GLO: ind=index+1; break;
case SYS_GAL: ind=index+2; break;
case SYS_QZS: ind=index+3; break;
case SYS_SBS: ind=index+4; break;
case SYS_CMP: ind=index+5; break;
case SYS_IRN: ind=index+6; break;
default: ind=index ; break;
}
for (i=0,j=ver<=2.99?0:3;i<ind->n;i++,j+=16) {
if (ver<=2.99&&j>=80) { /* ver.2 */
if (!fgets(buff,MAXRNXLEN,fp)) break;
j=0;
}
if (stat) {
val[i]=str2num(buff,j,14)+ind->shift[i];
lli[i]=(uint8_t)str2num(buff,j+14,1)&3;
/* measurement std from receiver */
std[i]=(uint8_t)str2num(buff,j+15,1);
}
}
if (!stat) return 0;
for (i=0;i<NFREQ+NEXOBS;i++) {
obs->P[i]=obs->L[i]=0.0; obs->D[i]=0.0f;
obs->SNR[i]=obs->LLI[i]=obs->Lstd[i]=obs->Pstd[i]=obs->code[i]=0;
}
/* initialize iobs and nobs */
for (f = 0; f < NFREQ; f++) {
nobs[f] = 0;
for (j = 0; j < MAXOBSTYPE / 4; j++) {
iobs[f][j] = -1;
}
}
/* 每个频率伪距观测值类型个数统计 */
for (i = 0; i < ind->n; i++) { /* assign position in observation data */
ifrq[i] = -1; // initial ifrq
if (ind->type[i] != 0) continue; // not pseudo-range type
if (val[i] == 0.0) continue; // null value
f = ind->idx[i]; // frequancy index
iobs[f][nobs[f]++] = i;
}
/* 每个频率选择一个码类型 */
for (f = 0; f < NFREQ; f++) {
/* 具有最高优先级的码类型 */
for (i = 0, maxpri = -1, imax = -1; i < nobs[f]; i++) {
if (ind->pri[iobs[f][i]] > maxpri) {
imax = i;
maxpri = ind->pri[iobs[f][i]];
}
}
if (imax < 0) continue;
/* the pesudo-range obs of frequency f with highest priority */
for (i = 0; i < ind->n; i++) {
if (ind->code[i] == ind->code[iobs[f][imax]]) {
ifrq[i] = f;
}
}
}
/* assign index of extended observation data */
for (f = 0; f < NEXOBS; f++) {
/* 具有最高优先级的码类型 */
for (i = 0, maxpri = -1, imax = -1; i < nobs[f]; i++) {
if (ifrq[iobs[f][i]] > 0) continue;
if (ind->pri[iobs[f][i]] > maxpri) {
imax = i;
maxpri = ind->pri[iobs[f][i]];
}
}
if (imax < 0) continue;
/* the pesudo-range obs of frequency f with highest priority */
for (i = 0; i < ind->n; i++) {
if (ind->code[i] == ind->code[iobs[f][imax]]) {
ifrq[i] = f + NFREQ;
}
}
}
/* save observation data */
for (i=0;i<ind->n;i++) {
if (ifrq[i]<0 || ifrq[i] >= NFREQ + NEXOBS ||(val[i]==0.0&&lli[i]==0)) continue;
switch (ind->type[i]) {
case 0: obs->P[ifrq[i]]=val[i];
obs->code[ifrq[i]]=ind->code[i];
obs->Pstd[ifrq[i]]=std[i]>0?std[i]:1;
break;
case 1: obs->L[ifrq[i]]=val[i];
obs->LLI[ifrq[i]]=lli[i];
obs->Lstd[ifrq[i]]=std[i]>0?std[i]:1;
break;
case 2: obs->D[ifrq[i]]=(float)val[i]; break;
case 3: obs->SNR[ifrq[i]]=(uint16_t)(val[i]/SNR_UNIT+0.5); break;
}
}
trace(4,"decode_obsdata: time=%s sat=%2d\n",time_str(obs->time,0),obs->sat);
return 1;
}