need a second pair of eyes (please)

Hi

i’m having trouble thinking my way out of a paper bag this morning.

I’m trying to write a simple web-server for an arduino app. previous versions have worked fine for a few years apart from some memory leaks causing sporadic reboots.

this is the code as I currently have it

void jlisten(){
  int j =0;
  bool currentLineIsBlank = false;
  bool isGet = false;
  bool isPost = false;
  char line[100];
  byte l = 0;
  bool isAuthorised = false;
  char* action;
  char* data;
  char verb;
  char auth[] = "****"; //redacted
  int contentlength;
  char* buff;
  String _day;
  StoredAlarm a;
  uint8_t hr; 
  uint8_t min;
  
  if(jserver.available()){
    EthernetClient jclient = jserver.available();
    if(jclient){
      while(char c = jclient.read()){
        Serial.print(c);
        wdt_reset();
        if(c == '\n' && currentLineIsBlank){
             
          Serial.print("data 28: ");
           Serial.println(data);
            if(isPost){
              memset(&line, 0, contentlength + 1);
              for(int i = 0; i < contentlength; i++){
                wdt_reset();
                c= jclient.read();
                line[i] = c;
              }

              action = strtok(line, "=");
              action = strtok(NULL, "&");
              verb = action[0];
              free(action);
              data = strtok(NULL,"=");
              data = strtok(NULL,"=");
            }
            break;
           
         } else if(c == '\n') {
            Serial.print("data 48:  ");
            Serial.println(data);
            //Serial.println("setting current line is blank");
            currentLineIsBlank = true;
            
            if(strncmp(line, "POST", 4) == 0){
              isPost = true;
            } else if (strncmp(line,"GET /",5) == 0 && !isGet) {
              Serial.println("doing get");
              isGet = true;
              action = strtok(line, "=");
              action = strtok(NULL, "&");
              verb = action[0];
              free(action);
              data = strtok(NULL,"=");
              Serial.print("data 63:");
              Serial.println(data);
              data = strtok(NULL," ");
              Serial.print("data 66: ");
              Serial.println(data);
            } else if (strncmp(line, "Auth", 4) == 0 ){
              Serial.println("doing auth"); Serial.print("Data 69: ");
              Serial.println(data);
              char buff[25];
              for (int i = 21; i < 45; i++){
                buff[i - 21] = line[i];
                buff[i - 20] = '\0';
              }
              if ( strncmp(auth, buff, 24) == 0 ){
                isAuthorised = true;
                Serial.print("Data 78: ");
                Serial.println(data);
                if(isGet) break;
              }
              
            } else if(strncmp(line, "Cont", 4) == 0) {
                sscanf( line, "Content-Length: %d", &contentlength);
            }
            free(line);
            l=0;
         } else if( c != '\r'){
             currentLineIsBlank = false;
             line[l] = c;
             line[l + 1] = '\0';
             l++;
         }
      }
     if(!isAuthorised){
       jclient.print(F("HTTP/1.1 "));
       jclient.println(F("401 Authorization Required"));
       jclient.println(F("Content-Type: text/html"));
       jclient.println(F("WWW-Authenticate: Basic realm=\"jIrrigation\""));  
       jclient.println(F("Connection: close"));
       jclient.println();
       delay(10);
       jclient.stop();
       return;
     }
     
     jclient.println(F("HTTP/1.1"));
     jclient.println(F(" 200 OK"));
     jclient.println(F("Content-Type: text/html"));
     jclient.println(F("Connection: close"));
     jclient.println();
     
    switch( verb ){     
        //omitted to fit within the 9000 char limit of the forum
    }
    jclient.println();
    jclient.flush();
    delay(10);
    jclient.stop();
    
  }
}

somehow the data variable is being overwritten and I cannot see where. the results i get from the serial monitor are as follows

Version 2015 July v0.3.0
My IP address: 192.168.2.10.
Irrigation: 1
Num Alarms: 0
GET /?action=4&data=2 HTTP/1.1
data 48:  
doing get
data 63:data
data 66: 2
Host: 192.168.2.10
data 48:  2
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.10; rv:37.0) Gecko/20100101 Firefox/37.0
data 48:  5.0 (Macintosh; Intel Mac OS X 10.10; rv:37.0) Gecko/20100101 Firefox/37.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
data 48:  plication/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-US,en;q=0.5
data 48:  US,en;q=0.5
Accept-Encoding: gzip, deflate
data 48:  p, deflate
Authorization: Basic *****
data 48:   *****
doing auth
Data 69:  *****
Data 78:  *****
data:  *****

(the asterisks redact the username/pwd auth combo)
so logically somewhere the data variable is being overwritten with the input from each read line of headers.

can anyone point out to me where I am missing the obvious?

thanks in advance
Justin

You are either running out of SRAM or, more likely, you are overflowing an array,

possibly, but there should be loads of sRam. more than 1k for sure.

as to the overflow, even were that the case from where is the 'wrong' data being assigned to the array?

I guess this must be a memory contiguity issue as the data pointer is reading from the memory in which the line array is stored.

i will copy the data variable to a separate char array then. less memory efficient but solves the immediate issue.

thanks

The local memory is allocated linear. For example, if you overflow the line array, it will overwrite all subsequent variables.

// if you overflow this array...
  char line[100];
// it will overwrite into here...
  byte l = 0;
// ...and here...
  bool isAuthorised = false;
// ...and here...
  char* action;
// ...and here...
  char* data;
// ...and here...
  char verb;
// ...and here...
  char auth[] = "****"; //redacted
// ...and here...
  int contentlength;
// ...and here...
  char* buff;
// ...and here
  String _day;

aha.

thanks. that helps.

so i should have just added this line to the final else if. how silly.

and the reason i never saw the problem before is that the server only interacts normally with curl where i specify the headers that get sent. d'oh.

if(l>=100)continue;