Take the 2-minute tour ×
Information Security Stack Exchange is a question and answer site for Information security professionals. It's 100% free, no registration required.

I started writing a a simple protocol lexer and parser for STOMP using flex and bison. Does anyone know of any security issues that might result from this?

Edit: Added code.


%{
 /* Tokenizer for the STOMP 1.2 protocol. */
%}

%%
 /* Client commands. */
"SEND"                          return T_CLIENT_SEND;
"SUBSCRIBE"                     return T_CLIENT_SUBSCRIBE;
"UNSUBSCRIBE"                   return T_CLIENT_UNSUBSCRIBE;
"BEGIN"                         return T_CLIENT_BEGIN;
"COMMIT"                        return T_CLIENT_COMMIT;
"ABORT"                         return T_CLIENT_ABORT;
"ACK"                           return T_CLIENT_ACK;
"NACK"                          return T_CLIENT_NACK;
"DISCONNECT"                    return T_CLIENT_DISCONNECT;
"CONNECT"                       return T_CLIENT_CONNECT;
"STOMP"                         return T_CLIENT_STOMP;

 /* Server Commands. */
"CONNECTED"                     return T_SERVER_CONNECTED;
"MESSAGE"                       return T_SERVER_MESSAGE;
"RECEIPT"                       return T_SERVER_RECEIPT;
"ERROR"                         return T_SERVER_ERROR;

 /* Other tokens */
\x00                            return T_NULL;
\x0A                            return T_LF;
\x0D                            return T_CR;
[\x0D]?\x0A                     return T_EOL;
:                               return T_COLON;
[0-255]                         return T_OCTET;
 /* (T_OCTET - (T_LF + T_CR + T_COLON)) */
[\x00-\x09\x0B-\x0C\x0E-\xFF]   return T_SPECIAL;

%%

%{
 /* Parser for the STOMP 1.2 protocol. */
 #include <stdio.h>
 #include "../client_protocol_stomp.h"

 extern stomp_node_t stomp_frame_root;

 void yyerror(const char *str) {
     fprintf(stderr,"error: %s\n",str);
 }

 int yywrap() {
     return 1;
 }

 int yylex(void);
%}

%defines
%error-verbose

/* Tokens for header file generation. */
%token T_CLIENT_SEND T_CLIENT_SUBSCRIBE T_CLIENT_UNSUBSCRIBE T_CLIENT_BEGIN
%token T_CLIENT_COMMIT T_CLIENT_ABORT T_CLIENT_ACK T_CLIENT_NACK
%token T_CLIENT_DISCONNECT T_CLIENT_CONNECT T_CLIENT_STOMP T_SERVER_CONNECTED
%token T_SERVER_MESSAGE T_SERVER_RECEIPT T_SERVER_ERROR T_NULL T_LF T_CR T_EOL
%token T_COLON T_OCTET T_SPECIAL

%union {
    stomp_node_t node;
}

/* Map tokens and non-terminals to fiels in the yylval union. */
/* %type <node> factor term exp */

%%
expression     : frame { /* stomp_frame_root = $1; */ }
               ;

frame          : frame_command
                 frame_command
                 T_EOL
                 frame_octet
                 T_NULL
                 frame_eol
               ;

frame_command  : command T_EOL
               ;

frame_header   : header T_EOL
               | header T_EOL frame_header
               ;

frame_octet    : T_OCTET
               | T_OCTET frame_octet
               ;

frame_eol      : T_EOL
               | T_EOL frame_eol
               ;

command        : client_command 
               | server_command
               ;

client_command : T_CLIENT_SEND
               | T_CLIENT_SUBSCRIBE
               | T_CLIENT_UNSUBSCRIBE
               | T_CLIENT_BEGIN
               | T_CLIENT_COMMIT
               | T_CLIENT_ABORT
               | T_CLIENT_ACK
               | T_CLIENT_NACK
               | T_CLIENT_DISCONNECT
               | T_CLIENT_CONNECT
               | T_CLIENT_STOMP
               ;

server_command : T_SERVER_CONNECTED
               | T_SERVER_MESSAGE
               | T_SERVER_RECEIPT
               | T_SERVER_ERROR
               ;

header         : header_name T_COLON header_value
               ;

header_name    : T_SPECIAL
               ;

header_value   : header_name
               | header_name header_value
               ;
%%
share|improve this question
add comment

1 Answer

up vote 5 down vote accepted

Bison and flex are reasonable tools to write parsers for protocols which fit in an LALR(1) grammar; but they are just tools like, e.g., a C compiler. It is still up to you not to do anything wrong with them. For that matter, bison and flex mean that you are about to implement your code with C or C++, languages which are known to be difficult to handle properly and prone to trigger security holes, especially because of pointer aliasing issues, manual memory management, lack of decent character string handling facilities, and unchecked array bounds. These are C issues, not bison issues, but you'll get them nonetheless.

LALR(1) parsing can be a bit confusing because you tend to get the "reduce" rules on a right-to-left basis. When you write the code attached to the grammar clauses, this can make things awkward (you have to handle the leaves of the syntax tree is a mostly context-free way).

The good thing about flex and bison is that they are systematic: they will implement all the corner cases of the grammar. That's a great property for security (most of secure coding is about covering all possible cases without forgetting any).

share|improve this answer
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.