(root)/
gcc-13.2.0/
gcc/
testsuite/
gcc.dg/
analyzer/
infinite-recursion-pr108524-1.c
       1  /* Reduced from qemu-7.2.0's qobject/json-parser.c, which
       2     is licensed under LGPLv2.1 or later.  */
       3  
       4  /* { dg-additional-options "-fno-analyzer-call-summaries -Wno-analyzer-too-complex" } */
       5  
       6  #define NULL ((void *)0)
       7  typedef __builtin_va_list va_list;
       8  
       9  typedef struct _GQueue GQueue;
      10  typedef struct Error Error;
      11  typedef struct QList QList;
      12  typedef struct QObject QObject;
      13  
      14  struct QObjectBase_ {
      15    /* [...snip...] */
      16  };
      17  
      18  
      19  struct QObject {
      20    struct QObjectBase_ base;
      21  };
      22  
      23  #define QOBJECT(obj) ((QObject *)obj)
      24  #define qobject_unref(OBJ) /* [...snip...] */
      25  
      26  typedef struct QTailQLink {
      27    void *tql_next;
      28    struct QTailQLink *tql_prev;
      29  } QTailQLink;
      30  
      31  struct QList {
      32    struct QObjectBase_ base;
      33    union {
      34      struct QListEntry *tqh_first;
      35      QTailQLink tqh_circ;
      36    } head;
      37  };
      38  QList *qlist_new(void);
      39  void qlist_append_obj(QList *qlist, QObject *obj);
      40  
      41  typedef enum json_token_type {
      42    /* [...snip...] */			      
      43    JSON_LSQUARE,
      44    JSON_RSQUARE,
      45    /* [...snip...] */			      
      46    JSON_COMMA,
      47    /* [...snip...] */			      
      48    JSON_KEYWORD,
      49    /* [...snip...] */			      
      50  } JSONTokenType;
      51  typedef struct JSONToken JSONToken;
      52  
      53  struct JSONToken {
      54    JSONTokenType type;
      55    int x;
      56    int y;
      57    char str[];
      58  };
      59  
      60  typedef struct JSONParserContext {
      61    Error *err;
      62    JSONToken *current;
      63    GQueue *buf;
      64    va_list *ap;
      65  } JSONParserContext;
      66  static QObject *parse_value(JSONParserContext *ctxt);
      67  
      68  JSONToken *parser_context_pop_token(JSONParserContext *ctxt);
      69  JSONToken *parser_context_peek_token(JSONParserContext *ctxt);
      70  
      71  static QObject *parse_array(JSONParserContext *ctxt) {
      72    QList *list = NULL;
      73    JSONToken *token, *peek;
      74  
      75    token = parser_context_pop_token(ctxt);
      76  
      77    list = qlist_new();
      78  
      79    peek = parser_context_peek_token(ctxt);
      80    if (peek == NULL) {
      81      goto out;
      82    }
      83  
      84    if (peek->type != JSON_RSQUARE) {
      85      QObject *obj;
      86  
      87      obj = parse_value(ctxt); /* { dg-bogus "infinite recursion" } */
      88      if (obj == NULL) {
      89        goto out;
      90      }
      91  
      92      qlist_append_obj(list, obj);
      93  
      94      token = parser_context_pop_token(ctxt);
      95      if (token == NULL) {
      96        goto out;
      97      }
      98  
      99      while (token->type != JSON_RSQUARE) {
     100        if (token->type != JSON_COMMA) {
     101          goto out;
     102        }
     103  
     104        obj = parse_value(ctxt);
     105        if (obj == NULL) {
     106          goto out;
     107        }
     108  
     109        qlist_append_obj(list, obj);
     110  
     111        token = parser_context_pop_token(ctxt);
     112        if (token == NULL) {
     113          goto out;
     114        }
     115      }
     116    } else {
     117      (void)parser_context_pop_token(ctxt);
     118    }
     119  
     120    return QOBJECT(list);
     121  
     122  out:
     123    qobject_unref(list);
     124    return NULL;
     125  }
     126  
     127  QObject *parse_keyword(JSONParserContext *ctxt);
     128  
     129  QObject *parse_value(JSONParserContext *ctxt) {
     130    JSONToken *token;
     131  
     132    token = parser_context_peek_token(ctxt);
     133    if (token == NULL) {
     134      return NULL;
     135    }
     136  
     137    switch (token->type) {
     138    case JSON_LSQUARE:
     139      return parse_array(ctxt); /* { dg-bogus "infinite recursion" } */
     140    case JSON_KEYWORD:
     141      return parse_keyword(ctxt);
     142    default:
     143      return NULL;
     144    }
     145  }