From a7c0fe1d8d8d89204f5c25a72d556d3d67b32d35 Mon Sep 17 00:00:00 2001 From: Adam Dickmeiss Date: Sat, 1 Apr 2006 11:45:23 +0000 Subject: [PATCH] Fixed 523: PQF parser does not properly diagnose @prox syntax errors. Added a few PQF parser diagnostics to improve error messages. Catch terms that aren't unsigned ints.. E.g. the invalid @attr p=q x . --- include/yaz/pquery.h | 8 ++++- src/pquery.c | 62 +++++++++++++++++++++++++++++++++----- test/Makefile.am | 5 +-- test/tstpquery.c | 82 ++++++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 147 insertions(+), 10 deletions(-) create mode 100644 test/tstpquery.c diff --git a/include/yaz/pquery.h b/include/yaz/pquery.h index 183201e..44813f8 100644 --- a/include/yaz/pquery.h +++ b/include/yaz/pquery.h @@ -23,7 +23,7 @@ * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE * OF THIS SOFTWARE. * - * $Id: pquery.h,v 1.7 2005-06-25 15:46:03 adam Exp $ + * $Id: pquery.h,v 1.8 2006-04-01 11:45:23 adam Exp $ */ /** * \file pquery.h @@ -78,6 +78,12 @@ YAZ_EXPORT int yaz_pqf_error (YAZ_PQF_Parser p, const char **msg, size_t *off); /* internal failure */ #define YAZ_PQF_ERROR_INTERNAL 6 +/* bad proximity args */ +#define YAZ_PQF_ERROR_PROXIMITY 7 + +/* bad unsigned integer */ +#define YAZ_PQF_ERROR_BAD_INTEGER 8 + YAZ_END_CDECL #endif diff --git a/src/pquery.c b/src/pquery.c index 9ee3584..99786fc 100644 --- a/src/pquery.c +++ b/src/pquery.c @@ -2,7 +2,7 @@ * Copyright (C) 1995-2005, Index Data ApS * See the file LICENSE for details. * - * $Id: pquery.c,v 1.7 2006-02-19 18:34:13 adam Exp $ + * $Id: pquery.c,v 1.8 2006-04-01 11:45:23 adam Exp $ */ /** * \file pquery.c @@ -194,6 +194,7 @@ static int p_query_parse_attr(struct yaz_pqf_parser *li, ODR o, char **attr_clist, oid_value *attr_set) { const char *cp; + if (!(cp = strchr (li->lex_buf, '=')) || (size_t) (cp-li->lex_buf) > li->lex_len) { @@ -221,8 +222,13 @@ static int p_query_parse_attr(struct yaz_pqf_parser *li, ODR o, else attr_set[num_attr] = VAL_NONE; } + if (*li->lex_buf < '0' || *li->lex_buf > '9') + { + li->error = YAZ_PQF_ERROR_BAD_INTEGER; + return 0; + } attr_list[2*num_attr] = atoi(li->lex_buf); - cp++; + cp++; if (*cp >= '0' && *cp <= '9') { attr_list[2*num_attr+1] = atoi (cp); @@ -403,29 +409,54 @@ static Z_ProximityOperator *rpn_proximity (struct yaz_pqf_parser *li, ODR o) p->exclusion = odr_intdup (o, 1); else if (*li->lex_buf == '0') p->exclusion = odr_intdup (o, 0); - else + else if (*li->lex_buf == 'v' || *li->lex_buf == 'n') p->exclusion = NULL; + else + { + li->error = YAZ_PQF_ERROR_PROXIMITY; + return NULL; + } if (!lex (li)) { li->error = YAZ_PQF_ERROR_MISSING; return NULL; } - p->distance = odr_intdup (o, atoi(li->lex_buf)); + if (*li->lex_buf >= '0' && *li->lex_buf <= '9') + p->distance = odr_intdup (o, atoi (li->lex_buf)); + else + { + li->error = YAZ_PQF_ERROR_BAD_INTEGER; + return NULL; + } if (!lex (li)) { li->error = YAZ_PQF_ERROR_MISSING; return NULL; } - p->ordered = odr_intdup (o, atoi (li->lex_buf)); + if (*li->lex_buf == '1') + p->ordered = odr_intdup (o, 1); + else if (*li->lex_buf == '0') + p->ordered = odr_intdup (o, 0); + else + { + li->error = YAZ_PQF_ERROR_PROXIMITY; + return NULL; + } if (!lex (li)) { li->error = YAZ_PQF_ERROR_MISSING; return NULL; } - p->relationType = odr_intdup (o, atoi (li->lex_buf)); + if (*li->lex_buf >= '0' && *li->lex_buf <= '9') + p->relationType = odr_intdup (o, atoi (li->lex_buf)); + else + { + li->error = YAZ_PQF_ERROR_BAD_INTEGER; + return NULL; + } if (!lex (li)) { @@ -439,12 +470,25 @@ static Z_ProximityOperator *rpn_proximity (struct yaz_pqf_parser *li, ODR o) else p->which = atoi (li->lex_buf); + if (p->which != Z_ProximityOperator_known + && p->which != Z_ProximityOperator_private) + { + li->error = YAZ_PQF_ERROR_PROXIMITY; + return NULL; + } + if (!lex (li)) { li->error = YAZ_PQF_ERROR_MISSING; return NULL; } - p->u.known = odr_intdup (o, atoi(li->lex_buf)); + if (*li->lex_buf >= '0' && *li->lex_buf <= '9') + p->u.known = odr_intdup (o, atoi(li->lex_buf)); + else + { + li->error = YAZ_PQF_ERROR_BAD_INTEGER; + return NULL; + } return p; } @@ -800,6 +844,10 @@ int yaz_pqf_error (YAZ_PQF_Parser p, const char **msg, size_t *off) *msg = "bad attribute specification"; break; case YAZ_PQF_ERROR_INTERNAL: *msg = "internal error"; break; + case YAZ_PQF_ERROR_PROXIMITY: + *msg = "proximity error"; break; + case YAZ_PQF_ERROR_BAD_INTEGER: + *msg = "bad integer"; break; default: *msg = "unknown error"; break; } diff --git a/test/Makefile.am b/test/Makefile.am index 790603c..fd5eda6 100644 --- a/test/Makefile.am +++ b/test/Makefile.am @@ -1,9 +1,9 @@ ## Copyright (C) 1994-2006, Index Data ## All rights reserved. -## $Id: Makefile.am,v 1.11 2006-01-27 17:33:15 adam Exp $ +## $Id: Makefile.am,v 1.12 2006-04-01 11:45:23 adam Exp $ check_PROGRAMS = tsticonv tstnmem tstmatchstr tstwrbuf tstodr tstccl tstlog \ - tstsoap1 tstsoap2 tstodrstack tstlogthread tstxmlquery + tstsoap1 tstsoap2 tstodrstack tstlogthread tstxmlquery tstpquery check_SCRIPTS = tstcql.sh tstmarc.sh TESTS = $(check_PROGRAMS) $(check_SCRIPTS) @@ -42,4 +42,5 @@ tstsoap1_SOURCES = tstsoap1.c tstsoap2_SOURCES = tstsoap2.c tstlogthread_SOURCES = tstlogthread.c tstxmlquery_SOURCES = tstxmlquery.c +tstpquery_SOURCES = tstpquery.c diff --git a/test/tstpquery.c b/test/tstpquery.c new file mode 100644 index 0000000..c36e65d --- /dev/null +++ b/test/tstpquery.c @@ -0,0 +1,82 @@ +/* + * Copyright (C) 1995-2005, Index Data ApS + * See the file LICENSE for details. + * + * $Id: tstpquery.c,v 1.1 2006-04-01 11:45:23 adam Exp $ + */ + +#include +#include + +#include +#include +#include +#include + +int expect_pqf(const char *pqf, const char *expect_pqf, int expect_error) +{ + YAZ_PQF_Parser parser = yaz_pqf_create(); + int res = 0; + ODR odr = odr_createmem(ODR_ENCODE); + Z_RPNQuery *rpn; + + if (!parser) + return 0; + + if (!odr) + return 0; + + rpn = yaz_pqf_parse(parser, odr, pqf); + + if (!rpn) + { + const char *msg; + size_t offset; + int got_error = yaz_pqf_error (parser, &msg, &offset); + + if (expect_error == got_error) + res = 1; + } + else if (expect_error == YAZ_PQF_ERROR_NONE) + { + WRBUF wrbuf = wrbuf_alloc(); + + if (wrbuf) + { + yaz_rpnquery_to_wrbuf(wrbuf, rpn); + + if (!strcmp(wrbuf_buf(wrbuf), expect_pqf)) + res = 1; + wrbuf_free(wrbuf, 1); + } + } + yaz_pqf_destroy(parser); + odr_destroy(odr); + return res; +} + +static void tst() +{ + YAZ_CHECK(expect_pqf("a", "@attrset Bib-1 a", YAZ_PQF_ERROR_NONE)); + YAZ_CHECK(expect_pqf("@attr 1=4 a", "@attrset Bib-1 @attr 1=4 a", YAZ_PQF_ERROR_NONE)); + YAZ_CHECK(expect_pqf("a b", "", YAZ_PQF_ERROR_EXTRA)); + YAZ_CHECK(expect_pqf("@prox 0 0 0 0 k 0 a b", + "@attrset Bib-1 @prox 0 0 0 0 k 0 a b", + YAZ_PQF_ERROR_NONE)); +} + +int main (int argc, char **argv) +{ + YAZ_CHECK_INIT(argc, argv); + tst(); + YAZ_CHECK_TERM; +} + +/* + * Local variables: + * c-basic-offset: 4 + * indent-tabs-mode: nil + * End: + * vim: shiftwidth=4 tabstop=8 expandtab + */ + -- 1.7.10.4