mirror of
				https://github.com/MariaDB/server.git
				synced 2025-11-04 04:46:15 +01:00 
			
		
		
		
	I checked all stack overflow potential problems found with gcc -Wstack-usage=16384 and clang -Wframe-larger-than=16384 -no-inline Fixes: Added '#pragma clang diagnostic ignored "-Wframe-larger-than="' to a lot of function to where stack usage large but resonable. - Added stack check warnings to BUILD scrips when using clang and debug. Function changed to use malloc instead allocating things on stack: - read_bootstrap_query() now allocates line_buffer (20000 bytes) with malloc() instead of using stack. This has a small performance impact but this is not releant for bootstrap. - mroonga grn_select() used 65856 bytes on stack. Changed it to use malloc(). - Wsrep_schema::replay_transaction() and Wsrep_schema::recover_sr_transactions(). - Connect zipOpen3() Not fixed: - mroonga/vendor/groonga/lib/expr.c grn_proc_call() uses 43712 byte on stack. However this is not easy to fix as the stack used is caused by a lot of code generated by defines. - Most changes in mroonga/groonga where only adding of pragmas to disable stack warnings. - rocksdb/options/options_helper.cc uses 20288 of stack space. (no reason to fix except to get rid of the compiler warning) - Causes using alloca() where the allocation size is resonable. - An issue in libmariadb (reported to connectors).
		
			
				
	
	
		
			174 lines
		
	
	
	
		
			4.5 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			174 lines
		
	
	
	
		
			4.5 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
/* Copyright (c) 2010, Oracle and/or its affiliates.
 | 
						|
 | 
						|
   This program is free software; you can redistribute it and/or modify
 | 
						|
   it under the terms of the GNU General Public License as published by
 | 
						|
   the Free Software Foundation; version 2 of the License.
 | 
						|
 | 
						|
   This program is distributed in the hope that it will be useful,
 | 
						|
   but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
						|
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
						|
   GNU General Public License for more details.
 | 
						|
 | 
						|
   You should have received a copy of the GNU General Public License
 | 
						|
   along with this program; if not, write to the Free Software Foundation,
 | 
						|
   51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA */
 | 
						|
 | 
						|
 | 
						|
#include "mariadb.h"
 | 
						|
#include <ctype.h>
 | 
						|
#include <string.h>
 | 
						|
#include "sql_bootstrap.h"
 | 
						|
#include <string>
 | 
						|
 | 
						|
static bool is_end_of_query(const char *line, size_t len,
 | 
						|
                            const std::string& delimiter)
 | 
						|
{
 | 
						|
  if (delimiter.length() > len)
 | 
						|
    return false;
 | 
						|
  return !strcmp(line + len-delimiter.length(),delimiter.c_str());
 | 
						|
}
 | 
						|
 | 
						|
static std::string delimiter= ";";
 | 
						|
extern "C" int read_bootstrap_query(char *query, int *query_length,
 | 
						|
                         fgets_input_t input, fgets_fn_t fgets_fn,
 | 
						|
                         int preserve_delimiter, int *error)
 | 
						|
{
 | 
						|
  char *line_buffer;
 | 
						|
  const char *line;
 | 
						|
  size_t len;
 | 
						|
  size_t query_len= 0;
 | 
						|
  int fgets_error= 0;
 | 
						|
  int exit_code= 0;
 | 
						|
  *error= 0;
 | 
						|
 | 
						|
  line_buffer= (char*) malloc(MAX_BOOTSTRAP_LINE_SIZE);
 | 
						|
 | 
						|
  *query_length= 0;
 | 
						|
  for ( ; ; )
 | 
						|
  {
 | 
						|
    line= (*fgets_fn)(line_buffer, MAX_BOOTSTRAP_LINE_SIZE, input, &fgets_error);
 | 
						|
    
 | 
						|
    if (error)
 | 
						|
      *error= fgets_error;
 | 
						|
 | 
						|
    if (fgets_error != 0)
 | 
						|
    {
 | 
						|
      exit_code= READ_BOOTSTRAP_ERROR;
 | 
						|
      break;
 | 
						|
    }
 | 
						|
      
 | 
						|
    if (line == NULL)
 | 
						|
    {
 | 
						|
      exit_code= (query_len == 0) ? READ_BOOTSTRAP_EOF : READ_BOOTSTRAP_ERROR;
 | 
						|
      break;
 | 
						|
    }
 | 
						|
 | 
						|
    len= strlen(line);
 | 
						|
 | 
						|
    /*
 | 
						|
      Remove trailing whitespace characters.
 | 
						|
      This assumes:
 | 
						|
      - no multibyte encoded character can be found at the very end of a line,
 | 
						|
      - whitespace characters from the "C" locale only.
 | 
						|
     which is sufficient for the kind of queries found
 | 
						|
     in the bootstrap scripts.
 | 
						|
    */
 | 
						|
    while (len && (isspace(line[len - 1])))
 | 
						|
      len--;
 | 
						|
    /*
 | 
						|
      Cleanly end the string, so we don't have to test len > x
 | 
						|
      all the time before reading line[x], in the code below.
 | 
						|
    */
 | 
						|
    line_buffer[len]= '\0';
 | 
						|
 | 
						|
    /* Skip blank lines */
 | 
						|
    if (len == 0)
 | 
						|
      continue;
 | 
						|
 | 
						|
    /* Skip # comments */
 | 
						|
    if (line[0] == '#')
 | 
						|
      continue;
 | 
						|
    
 | 
						|
    /* Skip -- comments */
 | 
						|
    if ((line[0] == '-') && (line[1] == '-'))
 | 
						|
      continue;
 | 
						|
 | 
						|
    size_t i=0;
 | 
						|
    while (line[i] == ' ')
 | 
						|
     i++;
 | 
						|
 | 
						|
    /* Skip -- comments */
 | 
						|
    if (line[i] == '-' && line[i+1] == '-')
 | 
						|
      continue;
 | 
						|
 | 
						|
    if (strncmp(line, "DELIMITER", 9) == 0)
 | 
						|
    {
 | 
						|
      const char *p= strrchr(line,' ');
 | 
						|
      if (!p || !p[1])
 | 
						|
      {
 | 
						|
        /* Invalid DELIMITER specifier */
 | 
						|
        exit_code= READ_BOOTSTRAP_ERROR;
 | 
						|
        break;
 | 
						|
      }
 | 
						|
      delimiter.assign(p+1);
 | 
						|
      if (preserve_delimiter)
 | 
						|
      {
 | 
						|
        memcpy(query,line,len);
 | 
						|
        query[len]=0;
 | 
						|
        *query_length = (int)len;
 | 
						|
        exit_code= READ_BOOTSTRAP_SUCCESS;
 | 
						|
        break;
 | 
						|
      }
 | 
						|
      continue;
 | 
						|
    }
 | 
						|
 | 
						|
    /* Append the current line to a multi line query. If the new line will make
 | 
						|
       the query too long, preserve the partial line to provide context for the
 | 
						|
       error message.
 | 
						|
    */
 | 
						|
    if (query_len + len + 1 >= MAX_BOOTSTRAP_QUERY_SIZE)
 | 
						|
    {
 | 
						|
      size_t new_len= MAX_BOOTSTRAP_QUERY_SIZE - query_len - 1;
 | 
						|
      if ((new_len > 0) && (query_len < MAX_BOOTSTRAP_QUERY_SIZE))
 | 
						|
      {
 | 
						|
        memcpy(query + query_len, line, new_len);
 | 
						|
        query_len+= new_len;
 | 
						|
      }
 | 
						|
      query[query_len]= '\0';
 | 
						|
      *query_length= (int)query_len;
 | 
						|
      exit_code= READ_BOOTSTRAP_QUERY_SIZE;
 | 
						|
      break;
 | 
						|
    }
 | 
						|
 | 
						|
    if (query_len != 0)
 | 
						|
    {
 | 
						|
      /*
 | 
						|
        Append a \n to the current line, if any,
 | 
						|
        to preserve the intended presentation.
 | 
						|
       */
 | 
						|
      query[query_len++]= '\n';
 | 
						|
    }
 | 
						|
    memcpy(query + query_len, line, len);
 | 
						|
    query_len+= len;
 | 
						|
 | 
						|
    if (is_end_of_query(line, len, delimiter))
 | 
						|
    {
 | 
						|
      /*
 | 
						|
        The last line is terminated by delimiter
 | 
						|
        Return the query found.
 | 
						|
      */
 | 
						|
      if (!preserve_delimiter)
 | 
						|
      {
 | 
						|
        query_len-= delimiter.length();
 | 
						|
        query[query_len++]= ';';
 | 
						|
      }
 | 
						|
      query[query_len]= 0;
 | 
						|
      *query_length= (int)query_len;
 | 
						|
      exit_code= READ_BOOTSTRAP_SUCCESS;
 | 
						|
      break;
 | 
						|
    }
 | 
						|
  }
 | 
						|
  free(line_buffer);
 | 
						|
  return exit_code;
 | 
						|
}
 | 
						|
 |