@@ -103,7 +103,9 @@ struct telnet_t {
103103 /* current subnegotiation telopt */
104104 unsigned char sb_telopt ;
105105 /* length of RFC1143 queue */
106- unsigned char q_size ;
106+ unsigned int q_size ;
107+ /* number of entries in RFC1143 queue */
108+ unsigned int q_cnt ;
107109};
108110
109111/* RFC1143 option negotiation state */
@@ -129,6 +131,9 @@ static const size_t _buffer_sizes[] = { 0, 512, 2048, 8192, 16384, };
129131static const size_t _buffer_sizes_count = sizeof (_buffer_sizes ) /
130132 sizeof (_buffer_sizes [0 ]);
131133
134+ /* RFC1143 option negotiation state table allocation quantum */
135+ #define Q_BUFFER_GROWTH_QUANTUM 4
136+
132137/* error generation function */
133138static telnet_error_t _error (telnet_t * telnet , unsigned line ,
134139 const char * func , telnet_error_t err , int fatal , const char * fmt ,
@@ -262,7 +267,7 @@ static INLINE int _check_telopt(telnet_t *telnet, unsigned char telopt,
262267 if (telnet -> telopts == 0 )
263268 return 0 ;
264269
265- /* loop unti found or end marker (us and him both 0) */
270+ /* loop until found or end marker (us and him both 0) */
266271 for (i = 0 ; telnet -> telopts [i ].telopt != -1 ; ++ i ) {
267272 if (telnet -> telopts [i ].telopt == telopt ) {
268273 if (us && telnet -> telopts [i ].us == TELNET_WILL )
@@ -285,7 +290,7 @@ static INLINE telnet_rfc1143_t _get_rfc1143(telnet_t *telnet,
285290 int i ;
286291
287292 /* search for entry */
288- for (i = 0 ; i != telnet -> q_size ; ++ i ) {
293+ for (i = 0 ; i != telnet -> q_cnt ; ++ i ) {
289294 if (telnet -> q [i ].telopt == telopt ) {
290295 return telnet -> q [i ];
291296 }
@@ -304,7 +309,7 @@ static INLINE void _set_rfc1143(telnet_t *telnet, unsigned char telopt,
304309 int i ;
305310
306311 /* search for entry */
307- for (i = 0 ; i != telnet -> q_size ; ++ i ) {
312+ for (i = 0 ; i != telnet -> q_cnt ; ++ i ) {
308313 if (telnet -> q [i ].telopt == telopt ) {
309314 telnet -> q [i ].state = Q_MAKE (us ,him );
310315 if (telopt != TELNET_TELOPT_BINARY )
@@ -325,17 +330,26 @@ static INLINE void _set_rfc1143(telnet_t *telnet, unsigned char telopt,
325330 * to the number of enabled options for most simple code, and it
326331 * allows for an acceptable number of reallocations for complex code.
327332 */
328- if ((qtmp = (telnet_rfc1143_t * )realloc (telnet -> q ,
329- sizeof (telnet_rfc1143_t ) * (telnet -> q_size + 4 ))) == 0 ) {
330- _error (telnet , __LINE__ , __func__ , TELNET_ENOMEM , 0 ,
331- "realloc() failed: %s" , strerror (errno ));
332- return ;
333+
334+ /* Did we reach the end of the table? */
335+ if (telnet -> q_cnt >= telnet -> q_size ) {
336+ /* Expand the size */
337+ if ((qtmp = (telnet_rfc1143_t * )realloc (telnet -> q ,
338+ sizeof (telnet_rfc1143_t ) *
339+ (telnet -> q_size + Q_BUFFER_GROWTH_QUANTUM ))) == 0 ) {
340+ _error (telnet , __LINE__ , __func__ , TELNET_ENOMEM , 0 ,
341+ "realloc() failed: %s" , strerror (errno ));
342+ return ;
343+ }
344+ memset (& qtmp [telnet -> q_size ], 0 , sizeof (telnet_rfc1143_t ) *
345+ Q_BUFFER_GROWTH_QUANTUM );
346+ telnet -> q = qtmp ;
347+ telnet -> q_size += Q_BUFFER_GROWTH_QUANTUM ;
333348 }
334- memset (& qtmp [telnet -> q_size ], 0 , sizeof (telnet_rfc1143_t ) * 4 );
335- telnet -> q = qtmp ;
336- telnet -> q [telnet -> q_size ].telopt = telopt ;
337- telnet -> q [telnet -> q_size ].state = Q_MAKE (us , him );
338- telnet -> q_size += 4 ;
349+ /* Add entry to end of table */
350+ telnet -> q [telnet -> q_cnt ].telopt = telopt ;
351+ telnet -> q [telnet -> q_cnt ].state = Q_MAKE (us , him );
352+ ++ telnet -> q_cnt ;
339353}
340354
341355/* send negotiation bytes */
@@ -909,8 +923,9 @@ void telnet_free(telnet_t *telnet) {
909923 /* free RFC1143 queue */
910924 if (telnet -> q ) {
911925 free (telnet -> q );
912- telnet -> q = 0 ;
926+ telnet -> q = NULL ;
913927 telnet -> q_size = 0 ;
928+ telnet -> q_cnt = 0 ;
914929 }
915930
916931 /* free the telnet structure itself */
0 commit comments