|  |  |  | @ -501,194 +501,190 @@ bool DetectContentPMATCHValidateCallback(const Signature *s) | 
		
	
		
			
				|  |  |  |  |  *  cannot set a depth, but we can set an offset of 'offset:1;'. This will | 
		
	
		
			
				|  |  |  |  |  *  make the mpm a bit more precise. | 
		
	
		
			
				|  |  |  |  |  */ | 
		
	
		
			
				|  |  |  |  | void DetectContentPropagateLimits(Signature *s) | 
		
	
		
			
				|  |  |  |  | static void PropagateLimits(Signature *s, SigMatch *sm_head) | 
		
	
		
			
				|  |  |  |  | { | 
		
	
		
			
				|  |  |  |  | #define VALIDATE(e)                                                                                \ | 
		
	
		
			
				|  |  |  |  |     if (!(e)) {                                                                                    \ | 
		
	
		
			
				|  |  |  |  |         return;                                                                                    \ | 
		
	
		
			
				|  |  |  |  |     } | 
		
	
		
			
				|  |  |  |  |     BUG_ON(s == NULL || s->init_data == NULL); | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |     uint32_t list = 0; | 
		
	
		
			
				|  |  |  |  |     for (list = 0; list < s->init_data->smlists_array_size; list++) { | 
		
	
		
			
				|  |  |  |  |         uint16_t offset = 0; | 
		
	
		
			
				|  |  |  |  |         uint16_t offset_plus_pat = 0; | 
		
	
		
			
				|  |  |  |  |         uint16_t depth = 0; | 
		
	
		
			
				|  |  |  |  |         bool has_active_depth_chain = false; | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |         bool has_depth = false; | 
		
	
		
			
				|  |  |  |  |         bool has_ends_with = false; | 
		
	
		
			
				|  |  |  |  |         uint16_t ends_with_depth = 0; | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |         SigMatch *sm = s->init_data->smlists[list]; | 
		
	
		
			
				|  |  |  |  |         for ( ; sm != NULL; sm = sm->next) { | 
		
	
		
			
				|  |  |  |  |             switch (sm->type) { | 
		
	
		
			
				|  |  |  |  |                 case DETECT_CONTENT: { | 
		
	
		
			
				|  |  |  |  |                     DetectContentData *cd = (DetectContentData *)sm->ctx; | 
		
	
		
			
				|  |  |  |  |                     if ((cd->flags & (DETECT_CONTENT_DEPTH|DETECT_CONTENT_OFFSET|DETECT_CONTENT_WITHIN|DETECT_CONTENT_DISTANCE)) == 0) { | 
		
	
		
			
				|  |  |  |  |                         offset = depth = 0; | 
		
	
		
			
				|  |  |  |  |                         offset_plus_pat = cd->content_len; | 
		
	
		
			
				|  |  |  |  |                         SCLogDebug("reset"); | 
		
	
		
			
				|  |  |  |  |                         has_active_depth_chain = false; | 
		
	
		
			
				|  |  |  |  |                         continue; | 
		
	
		
			
				|  |  |  |  |                     } | 
		
	
		
			
				|  |  |  |  |                     if (cd->flags & DETECT_CONTENT_NEGATED) { | 
		
	
		
			
				|  |  |  |  |                         offset = depth = 0; | 
		
	
		
			
				|  |  |  |  |                         offset_plus_pat = 0; | 
		
	
		
			
				|  |  |  |  |                         SCLogDebug("reset because of negation"); | 
		
	
		
			
				|  |  |  |  |                         has_active_depth_chain = false; | 
		
	
		
			
				|  |  |  |  |                         continue; | 
		
	
		
			
				|  |  |  |  |                     } | 
		
	
		
			
				|  |  |  |  |     uint16_t offset = 0; | 
		
	
		
			
				|  |  |  |  |     uint16_t offset_plus_pat = 0; | 
		
	
		
			
				|  |  |  |  |     uint16_t depth = 0; | 
		
	
		
			
				|  |  |  |  |     bool has_active_depth_chain = false; | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |     bool has_depth = false; | 
		
	
		
			
				|  |  |  |  |     bool has_ends_with = false; | 
		
	
		
			
				|  |  |  |  |     uint16_t ends_with_depth = 0; | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |     for (SigMatch *sm = sm_head; sm != NULL; sm = sm->next) { | 
		
	
		
			
				|  |  |  |  |         switch (sm->type) { | 
		
	
		
			
				|  |  |  |  |             case DETECT_CONTENT: { | 
		
	
		
			
				|  |  |  |  |                 DetectContentData *cd = (DetectContentData *)sm->ctx; | 
		
	
		
			
				|  |  |  |  |                 if ((cd->flags & (DETECT_CONTENT_DEPTH | DETECT_CONTENT_OFFSET | | 
		
	
		
			
				|  |  |  |  |                                          DETECT_CONTENT_WITHIN | DETECT_CONTENT_DISTANCE)) == 0) { | 
		
	
		
			
				|  |  |  |  |                     offset = depth = 0; | 
		
	
		
			
				|  |  |  |  |                     offset_plus_pat = cd->content_len; | 
		
	
		
			
				|  |  |  |  |                     SCLogDebug("reset"); | 
		
	
		
			
				|  |  |  |  |                     has_active_depth_chain = false; | 
		
	
		
			
				|  |  |  |  |                     continue; | 
		
	
		
			
				|  |  |  |  |                 } | 
		
	
		
			
				|  |  |  |  |                 if (cd->flags & DETECT_CONTENT_NEGATED) { | 
		
	
		
			
				|  |  |  |  |                     offset = depth = 0; | 
		
	
		
			
				|  |  |  |  |                     offset_plus_pat = 0; | 
		
	
		
			
				|  |  |  |  |                     SCLogDebug("reset because of negation"); | 
		
	
		
			
				|  |  |  |  |                     has_active_depth_chain = false; | 
		
	
		
			
				|  |  |  |  |                     continue; | 
		
	
		
			
				|  |  |  |  |                 } | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |                     if (cd->depth) { | 
		
	
		
			
				|  |  |  |  |                         has_depth = true; | 
		
	
		
			
				|  |  |  |  |                         has_active_depth_chain = true; | 
		
	
		
			
				|  |  |  |  |                     } | 
		
	
		
			
				|  |  |  |  |                 if (cd->depth) { | 
		
	
		
			
				|  |  |  |  |                     has_depth = true; | 
		
	
		
			
				|  |  |  |  |                     has_active_depth_chain = true; | 
		
	
		
			
				|  |  |  |  |                 } | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |                     SCLogDebug("sm %p depth %u offset %u distance %d within %d", sm, cd->depth, cd->offset, cd->distance, cd->within); | 
		
	
		
			
				|  |  |  |  |                     SCLogDebug("stored: offset %u depth %u offset_plus_pat %u", offset, depth, offset_plus_pat); | 
		
	
		
			
				|  |  |  |  |                 SCLogDebug("sm %p depth %u offset %u distance %d within %d", sm, cd->depth, | 
		
	
		
			
				|  |  |  |  |                         cd->offset, cd->distance, cd->within); | 
		
	
		
			
				|  |  |  |  |                 SCLogDebug("stored: offset %u depth %u offset_plus_pat %u", offset, depth, | 
		
	
		
			
				|  |  |  |  |                         offset_plus_pat); | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |                     if ((cd->flags & (DETECT_DEPTH | DETECT_CONTENT_WITHIN)) == 0) { | 
		
	
		
			
				|  |  |  |  |                         if (depth) | 
		
	
		
			
				|  |  |  |  |                             SCLogDebug("no within, reset depth"); | 
		
	
		
			
				|  |  |  |  |                         depth = 0; | 
		
	
		
			
				|  |  |  |  |                         has_active_depth_chain = false; | 
		
	
		
			
				|  |  |  |  |                     } | 
		
	
		
			
				|  |  |  |  |                     if ((cd->flags & DETECT_CONTENT_DISTANCE) == 0) { | 
		
	
		
			
				|  |  |  |  |                         if (offset_plus_pat) | 
		
	
		
			
				|  |  |  |  |                             SCLogDebug("no distance, reset offset_plus_pat & offset"); | 
		
	
		
			
				|  |  |  |  |                         offset_plus_pat = offset = 0; | 
		
	
		
			
				|  |  |  |  |                     } | 
		
	
		
			
				|  |  |  |  |                 if ((cd->flags & (DETECT_DEPTH | DETECT_CONTENT_WITHIN)) == 0) { | 
		
	
		
			
				|  |  |  |  |                     if (depth) | 
		
	
		
			
				|  |  |  |  |                         SCLogDebug("no within, reset depth"); | 
		
	
		
			
				|  |  |  |  |                     depth = 0; | 
		
	
		
			
				|  |  |  |  |                     has_active_depth_chain = false; | 
		
	
		
			
				|  |  |  |  |                 } | 
		
	
		
			
				|  |  |  |  |                 if ((cd->flags & DETECT_CONTENT_DISTANCE) == 0) { | 
		
	
		
			
				|  |  |  |  |                     if (offset_plus_pat) | 
		
	
		
			
				|  |  |  |  |                         SCLogDebug("no distance, reset offset_plus_pat & offset"); | 
		
	
		
			
				|  |  |  |  |                     offset_plus_pat = offset = 0; | 
		
	
		
			
				|  |  |  |  |                 } | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |                     SCLogDebug("stored: offset %u depth %u offset_plus_pat %u " | 
		
	
		
			
				|  |  |  |  |                                "has_active_depth_chain %s", | 
		
	
		
			
				|  |  |  |  |                             offset, depth, offset_plus_pat, | 
		
	
		
			
				|  |  |  |  |                             has_active_depth_chain ? "true" : "false"); | 
		
	
		
			
				|  |  |  |  |                     if (cd->flags & DETECT_CONTENT_DISTANCE && cd->distance >= 0) { | 
		
	
		
			
				|  |  |  |  |                         VALIDATE((uint32_t)offset_plus_pat + cd->distance <= UINT16_MAX); | 
		
	
		
			
				|  |  |  |  |                         offset = cd->offset = (uint16_t)(offset_plus_pat + cd->distance); | 
		
	
		
			
				|  |  |  |  |                         SCLogDebug("updated content to have offset %u", cd->offset); | 
		
	
		
			
				|  |  |  |  |                     } | 
		
	
		
			
				|  |  |  |  |                     if (has_active_depth_chain) { | 
		
	
		
			
				|  |  |  |  |                         if (offset_plus_pat && cd->flags & DETECT_CONTENT_WITHIN && | 
		
	
		
			
				|  |  |  |  |                                 cd->within >= 0) { | 
		
	
		
			
				|  |  |  |  |                             if (depth && depth > offset_plus_pat) { | 
		
	
		
			
				|  |  |  |  |                                 int32_t dist = 0; | 
		
	
		
			
				|  |  |  |  |                                 if (cd->flags & DETECT_CONTENT_DISTANCE && cd->distance > 0) { | 
		
	
		
			
				|  |  |  |  |                                     dist = cd->distance; | 
		
	
		
			
				|  |  |  |  |                                     SCLogDebug("distance to add: %u. depth + dist %u", dist, | 
		
	
		
			
				|  |  |  |  |                                             depth + dist); | 
		
	
		
			
				|  |  |  |  |                 SCLogDebug("stored: offset %u depth %u offset_plus_pat %u " | 
		
	
		
			
				|  |  |  |  |                            "has_active_depth_chain %s", | 
		
	
		
			
				|  |  |  |  |                         offset, depth, offset_plus_pat, has_active_depth_chain ? "true" : "false"); | 
		
	
		
			
				|  |  |  |  |                 if (cd->flags & DETECT_CONTENT_DISTANCE && cd->distance >= 0) { | 
		
	
		
			
				|  |  |  |  |                     VALIDATE((uint32_t)offset_plus_pat + cd->distance <= UINT16_MAX); | 
		
	
		
			
				|  |  |  |  |                     offset = cd->offset = (uint16_t)(offset_plus_pat + cd->distance); | 
		
	
		
			
				|  |  |  |  |                     SCLogDebug("updated content to have offset %u", cd->offset); | 
		
	
		
			
				|  |  |  |  |                 } | 
		
	
		
			
				|  |  |  |  |                 if (has_active_depth_chain) { | 
		
	
		
			
				|  |  |  |  |                     if (offset_plus_pat && cd->flags & DETECT_CONTENT_WITHIN && cd->within >= 0) { | 
		
	
		
			
				|  |  |  |  |                         if (depth && depth > offset_plus_pat) { | 
		
	
		
			
				|  |  |  |  |                             int32_t dist = 0; | 
		
	
		
			
				|  |  |  |  |                             if (cd->flags & DETECT_CONTENT_DISTANCE && cd->distance > 0) { | 
		
	
		
			
				|  |  |  |  |                                 dist = cd->distance; | 
		
	
		
			
				|  |  |  |  |                                 SCLogDebug( | 
		
	
		
			
				|  |  |  |  |                                         "distance to add: %u. depth + dist %u", dist, depth + dist); | 
		
	
		
			
				|  |  |  |  |                             } | 
		
	
		
			
				|  |  |  |  |                             SCLogDebug("depth %u + cd->within %u", depth, cd->within); | 
		
	
		
			
				|  |  |  |  |                             VALIDATE(depth + cd->within + dist >= 0 && | 
		
	
		
			
				|  |  |  |  |                                      depth + cd->within + dist <= UINT16_MAX); | 
		
	
		
			
				|  |  |  |  |                             depth = cd->depth = (uint16_t)(depth + cd->within + dist); | 
		
	
		
			
				|  |  |  |  |                         } else { | 
		
	
		
			
				|  |  |  |  |                             SCLogDebug("offset %u + cd->within %u", offset, cd->within); | 
		
	
		
			
				|  |  |  |  |                             VALIDATE(depth + cd->within >= 0 && depth + cd->within <= UINT16_MAX); | 
		
	
		
			
				|  |  |  |  |                             depth = cd->depth = (uint16_t)(offset + cd->within); | 
		
	
		
			
				|  |  |  |  |                         } | 
		
	
		
			
				|  |  |  |  |                         SCLogDebug("updated content to have depth %u", cd->depth); | 
		
	
		
			
				|  |  |  |  |                     } else { | 
		
	
		
			
				|  |  |  |  |                         if (cd->depth == 0 && depth != 0) { | 
		
	
		
			
				|  |  |  |  |                             if (cd->within > 0) { | 
		
	
		
			
				|  |  |  |  |                                 SCLogDebug("within %d distance %d", cd->within, cd->distance); | 
		
	
		
			
				|  |  |  |  |                                 if (cd->flags & DETECT_CONTENT_DISTANCE && cd->distance >= 0) { | 
		
	
		
			
				|  |  |  |  |                                     VALIDATE(offset_plus_pat + cd->distance >= 0 && | 
		
	
		
			
				|  |  |  |  |                                              offset_plus_pat + cd->distance <= UINT16_MAX); | 
		
	
		
			
				|  |  |  |  |                                     cd->offset = (uint16_t)(offset_plus_pat + cd->distance); | 
		
	
		
			
				|  |  |  |  |                                     SCLogDebug("updated content to have offset %u", cd->offset); | 
		
	
		
			
				|  |  |  |  |                                 } | 
		
	
		
			
				|  |  |  |  |                                 SCLogDebug("depth %u + cd->within %u", depth, cd->within); | 
		
	
		
			
				|  |  |  |  |                                 VALIDATE(depth + cd->within + dist >= 0 && | 
		
	
		
			
				|  |  |  |  |                                          depth + cd->within + dist <= UINT16_MAX); | 
		
	
		
			
				|  |  |  |  |                                 depth = cd->depth = (uint16_t)(depth + cd->within + dist); | 
		
	
		
			
				|  |  |  |  |                             } else { | 
		
	
		
			
				|  |  |  |  |                                 SCLogDebug("offset %u + cd->within %u", offset, cd->within); | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |                                 VALIDATE(depth + cd->within >= 0 && | 
		
	
		
			
				|  |  |  |  |                                          depth + cd->within <= UINT16_MAX); | 
		
	
		
			
				|  |  |  |  |                                 depth = cd->depth = (uint16_t)(offset + cd->within); | 
		
	
		
			
				|  |  |  |  |                             } | 
		
	
		
			
				|  |  |  |  |                             SCLogDebug("updated content to have depth %u", cd->depth); | 
		
	
		
			
				|  |  |  |  |                         } else { | 
		
	
		
			
				|  |  |  |  |                             if (cd->depth == 0 && depth != 0) { | 
		
	
		
			
				|  |  |  |  |                                 if (cd->within > 0) { | 
		
	
		
			
				|  |  |  |  |                                     SCLogDebug("within %d distance %d", cd->within, cd->distance); | 
		
	
		
			
				|  |  |  |  |                                     if (cd->flags & DETECT_CONTENT_DISTANCE && cd->distance >= 0) { | 
		
	
		
			
				|  |  |  |  |                                         VALIDATE(offset_plus_pat + cd->distance >= 0 && | 
		
	
		
			
				|  |  |  |  |                                                  offset_plus_pat + cd->distance <= UINT16_MAX); | 
		
	
		
			
				|  |  |  |  |                                         cd->offset = (uint16_t)(offset_plus_pat + cd->distance); | 
		
	
		
			
				|  |  |  |  |                                         SCLogDebug("updated content to have offset %u", cd->offset); | 
		
	
		
			
				|  |  |  |  |                                     } | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |                                     VALIDATE(depth + cd->within >= 0 && | 
		
	
		
			
				|  |  |  |  |                                              depth + cd->within <= UINT16_MAX); | 
		
	
		
			
				|  |  |  |  |                                     depth = cd->depth = (uint16_t)(cd->within + depth); | 
		
	
		
			
				|  |  |  |  |                                     SCLogDebug("updated content to have depth %u", cd->depth); | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |                                     if (cd->flags & DETECT_CONTENT_ENDS_WITH) { | 
		
	
		
			
				|  |  |  |  |                                         has_ends_with = true; | 
		
	
		
			
				|  |  |  |  |                                         if (ends_with_depth == 0) | 
		
	
		
			
				|  |  |  |  |                                             ends_with_depth = depth; | 
		
	
		
			
				|  |  |  |  |                                         ends_with_depth = MIN(ends_with_depth, depth); | 
		
	
		
			
				|  |  |  |  |                                     } | 
		
	
		
			
				|  |  |  |  |                                 depth = cd->depth = (uint16_t)(cd->within + depth); | 
		
	
		
			
				|  |  |  |  |                                 SCLogDebug("updated content to have depth %u", cd->depth); | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |                                 if (cd->flags & DETECT_CONTENT_ENDS_WITH) { | 
		
	
		
			
				|  |  |  |  |                                     has_ends_with = true; | 
		
	
		
			
				|  |  |  |  |                                     if (ends_with_depth == 0) | 
		
	
		
			
				|  |  |  |  |                                         ends_with_depth = depth; | 
		
	
		
			
				|  |  |  |  |                                     ends_with_depth = MIN(ends_with_depth, depth); | 
		
	
		
			
				|  |  |  |  |                                 } | 
		
	
		
			
				|  |  |  |  |                             } | 
		
	
		
			
				|  |  |  |  |                         } | 
		
	
		
			
				|  |  |  |  |                     } | 
		
	
		
			
				|  |  |  |  |                     if (cd->offset == 0) {// && offset != 0) {
 | 
		
	
		
			
				|  |  |  |  |                         if (cd->flags & DETECT_CONTENT_DISTANCE && cd->distance >= 0) { | 
		
	
		
			
				|  |  |  |  |                             cd->offset = offset_plus_pat; | 
		
	
		
			
				|  |  |  |  |                             SCLogDebug("update content to have offset %u", cd->offset); | 
		
	
		
			
				|  |  |  |  |                         } | 
		
	
		
			
				|  |  |  |  |                 } | 
		
	
		
			
				|  |  |  |  |                 if (cd->offset == 0) { // && offset != 0) {
 | 
		
	
		
			
				|  |  |  |  |                     if (cd->flags & DETECT_CONTENT_DISTANCE && cd->distance >= 0) { | 
		
	
		
			
				|  |  |  |  |                         cd->offset = offset_plus_pat; | 
		
	
		
			
				|  |  |  |  |                         SCLogDebug("update content to have offset %u", cd->offset); | 
		
	
		
			
				|  |  |  |  |                     } | 
		
	
		
			
				|  |  |  |  |                 } | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |                     if ((cd->flags & (DETECT_CONTENT_DEPTH|DETECT_CONTENT_OFFSET|DETECT_CONTENT_WITHIN|DETECT_CONTENT_DISTANCE)) == (DETECT_CONTENT_DISTANCE|DETECT_CONTENT_WITHIN) || | 
		
	
		
			
				|  |  |  |  |                             (cd->flags & (DETECT_CONTENT_DEPTH|DETECT_CONTENT_OFFSET|DETECT_CONTENT_WITHIN|DETECT_CONTENT_DISTANCE)) == (DETECT_CONTENT_DISTANCE)) { | 
		
	
		
			
				|  |  |  |  |                         if (cd->distance >= 0) { | 
		
	
		
			
				|  |  |  |  |                             // only distance
 | 
		
	
		
			
				|  |  |  |  |                             VALIDATE((uint32_t)offset_plus_pat + cd->distance <= UINT16_MAX); | 
		
	
		
			
				|  |  |  |  |                             offset = cd->offset = (uint16_t)(offset_plus_pat + cd->distance); | 
		
	
		
			
				|  |  |  |  |                             offset_plus_pat = offset + cd->content_len; | 
		
	
		
			
				|  |  |  |  |                             SCLogDebug("offset %u offset_plus_pat %u", offset, offset_plus_pat); | 
		
	
		
			
				|  |  |  |  |                         } | 
		
	
		
			
				|  |  |  |  |                     } | 
		
	
		
			
				|  |  |  |  |                     if (cd->flags & DETECT_CONTENT_OFFSET) { | 
		
	
		
			
				|  |  |  |  |                         offset = cd->offset; | 
		
	
		
			
				|  |  |  |  |                         offset_plus_pat = offset + cd->content_len; | 
		
	
		
			
				|  |  |  |  |                         SCLogDebug("stored offset %u offset_plus_pat %u", offset, offset_plus_pat); | 
		
	
		
			
				|  |  |  |  |                     } | 
		
	
		
			
				|  |  |  |  |                     if (cd->depth) { | 
		
	
		
			
				|  |  |  |  |                         depth = cd->depth; | 
		
	
		
			
				|  |  |  |  |                         SCLogDebug("stored depth now %u", depth); | 
		
	
		
			
				|  |  |  |  |                 if ((cd->flags & (DETECT_CONTENT_DEPTH | DETECT_CONTENT_OFFSET | | 
		
	
		
			
				|  |  |  |  |                                          DETECT_CONTENT_WITHIN | DETECT_CONTENT_DISTANCE)) == | 
		
	
		
			
				|  |  |  |  |                                 (DETECT_CONTENT_DISTANCE | DETECT_CONTENT_WITHIN) || | 
		
	
		
			
				|  |  |  |  |                         (cd->flags & (DETECT_CONTENT_DEPTH | DETECT_CONTENT_OFFSET | | 
		
	
		
			
				|  |  |  |  |                                              DETECT_CONTENT_WITHIN | DETECT_CONTENT_DISTANCE)) == | 
		
	
		
			
				|  |  |  |  |                                 (DETECT_CONTENT_DISTANCE)) { | 
		
	
		
			
				|  |  |  |  |                     if (cd->distance >= 0) { | 
		
	
		
			
				|  |  |  |  |                         // only distance
 | 
		
	
		
			
				|  |  |  |  |                         VALIDATE((uint32_t)offset_plus_pat + cd->distance <= UINT16_MAX); | 
		
	
		
			
				|  |  |  |  |                         offset = cd->offset = (uint16_t)(offset_plus_pat + cd->distance); | 
		
	
		
			
				|  |  |  |  |                         offset_plus_pat = offset + cd->content_len; | 
		
	
		
			
				|  |  |  |  |                         if (cd->flags & DETECT_CONTENT_ENDS_WITH) { | 
		
	
		
			
				|  |  |  |  |                             has_ends_with = true; | 
		
	
		
			
				|  |  |  |  |                             if (ends_with_depth == 0) | 
		
	
		
			
				|  |  |  |  |                                 ends_with_depth = depth; | 
		
	
		
			
				|  |  |  |  |                             ends_with_depth = MIN(ends_with_depth, depth); | 
		
	
		
			
				|  |  |  |  |                         } | 
		
	
		
			
				|  |  |  |  |                         SCLogDebug("offset %u offset_plus_pat %u", offset, offset_plus_pat); | 
		
	
		
			
				|  |  |  |  |                     } | 
		
	
		
			
				|  |  |  |  |                     if ((cd->flags & (DETECT_CONTENT_WITHIN|DETECT_CONTENT_DEPTH)) == 0) { | 
		
	
		
			
				|  |  |  |  |                         has_active_depth_chain = false; | 
		
	
		
			
				|  |  |  |  |                         depth = 0; | 
		
	
		
			
				|  |  |  |  |                     } | 
		
	
		
			
				|  |  |  |  |                     break; | 
		
	
		
			
				|  |  |  |  |                 } | 
		
	
		
			
				|  |  |  |  |                 case DETECT_PCRE: { | 
		
	
		
			
				|  |  |  |  |                     // relative could leave offset_plus_pat set.
 | 
		
	
		
			
				|  |  |  |  |                     const DetectPcreData *pd = (const DetectPcreData *)sm->ctx; | 
		
	
		
			
				|  |  |  |  |                     if (pd->flags & DETECT_PCRE_RELATIVE) { | 
		
	
		
			
				|  |  |  |  |                         depth = 0; | 
		
	
		
			
				|  |  |  |  |                     } else { | 
		
	
		
			
				|  |  |  |  |                         SCLogDebug("non-anchored PCRE not supported, reset offset_plus_pat & offset"); | 
		
	
		
			
				|  |  |  |  |                         offset_plus_pat = offset = depth = 0; | 
		
	
		
			
				|  |  |  |  |                 if (cd->flags & DETECT_CONTENT_OFFSET) { | 
		
	
		
			
				|  |  |  |  |                     offset = cd->offset; | 
		
	
		
			
				|  |  |  |  |                     offset_plus_pat = offset + cd->content_len; | 
		
	
		
			
				|  |  |  |  |                     SCLogDebug("stored offset %u offset_plus_pat %u", offset, offset_plus_pat); | 
		
	
		
			
				|  |  |  |  |                 } | 
		
	
		
			
				|  |  |  |  |                 if (cd->depth) { | 
		
	
		
			
				|  |  |  |  |                     depth = cd->depth; | 
		
	
		
			
				|  |  |  |  |                     SCLogDebug("stored depth now %u", depth); | 
		
	
		
			
				|  |  |  |  |                     offset_plus_pat = offset + cd->content_len; | 
		
	
		
			
				|  |  |  |  |                     if (cd->flags & DETECT_CONTENT_ENDS_WITH) { | 
		
	
		
			
				|  |  |  |  |                         has_ends_with = true; | 
		
	
		
			
				|  |  |  |  |                         if (ends_with_depth == 0) | 
		
	
		
			
				|  |  |  |  |                             ends_with_depth = depth; | 
		
	
		
			
				|  |  |  |  |                         ends_with_depth = MIN(ends_with_depth, depth); | 
		
	
		
			
				|  |  |  |  |                     } | 
		
	
		
			
				|  |  |  |  |                 } | 
		
	
		
			
				|  |  |  |  |                 if ((cd->flags & (DETECT_CONTENT_WITHIN | DETECT_CONTENT_DEPTH)) == 0) { | 
		
	
		
			
				|  |  |  |  |                     has_active_depth_chain = false; | 
		
	
		
			
				|  |  |  |  |                     break; | 
		
	
		
			
				|  |  |  |  |                     depth = 0; | 
		
	
		
			
				|  |  |  |  |                 } | 
		
	
		
			
				|  |  |  |  |                 default: { | 
		
	
		
			
				|  |  |  |  |                     SCLogDebug("keyword not supported, reset offset_plus_pat & offset"); | 
		
	
		
			
				|  |  |  |  |                 break; | 
		
	
		
			
				|  |  |  |  |             } | 
		
	
		
			
				|  |  |  |  |             case DETECT_PCRE: { | 
		
	
		
			
				|  |  |  |  |                 // relative could leave offset_plus_pat set.
 | 
		
	
		
			
				|  |  |  |  |                 const DetectPcreData *pd = (const DetectPcreData *)sm->ctx; | 
		
	
		
			
				|  |  |  |  |                 if (pd->flags & DETECT_PCRE_RELATIVE) { | 
		
	
		
			
				|  |  |  |  |                     depth = 0; | 
		
	
		
			
				|  |  |  |  |                 } else { | 
		
	
		
			
				|  |  |  |  |                     SCLogDebug("non-anchored PCRE not supported, reset offset_plus_pat & offset"); | 
		
	
		
			
				|  |  |  |  |                     offset_plus_pat = offset = depth = 0; | 
		
	
		
			
				|  |  |  |  |                     has_active_depth_chain = false; | 
		
	
		
			
				|  |  |  |  |                     break; | 
		
	
		
			
				|  |  |  |  |                 } | 
		
	
		
			
				|  |  |  |  |                 has_active_depth_chain = false; | 
		
	
		
			
				|  |  |  |  |                 break; | 
		
	
		
			
				|  |  |  |  |             } | 
		
	
		
			
				|  |  |  |  |             default: | 
		
	
		
			
				|  |  |  |  |                 SCLogDebug("keyword not supported, reset offset_plus_pat & offset"); | 
		
	
		
			
				|  |  |  |  |                 offset_plus_pat = offset = depth = 0; | 
		
	
		
			
				|  |  |  |  |                 has_active_depth_chain = false; | 
		
	
		
			
				|  |  |  |  |                 break; | 
		
	
		
			
				|  |  |  |  |         } | 
		
	
		
			
				|  |  |  |  |         /* apply anchored 'ends with' as depth to all patterns */ | 
		
	
		
			
				|  |  |  |  |         if (has_depth && has_ends_with) { | 
		
	
		
			
				|  |  |  |  |             sm = s->init_data->smlists[list]; | 
		
	
		
			
				|  |  |  |  |             for ( ; sm != NULL; sm = sm->next) { | 
		
	
		
			
				|  |  |  |  |                 switch (sm->type) { | 
		
	
		
			
				|  |  |  |  |                     case DETECT_CONTENT: { | 
		
	
		
			
				|  |  |  |  |                         DetectContentData *cd = (DetectContentData *)sm->ctx; | 
		
	
		
			
				|  |  |  |  |                         if (cd->depth == 0) | 
		
	
		
			
				|  |  |  |  |                             cd->depth = ends_with_depth; | 
		
	
		
			
				|  |  |  |  |                         cd->depth = MIN(ends_with_depth, cd->depth); | 
		
	
		
			
				|  |  |  |  |                         if (cd->depth) | 
		
	
		
			
				|  |  |  |  |                             cd->flags |= DETECT_CONTENT_DEPTH; | 
		
	
		
			
				|  |  |  |  |                         break; | 
		
	
		
			
				|  |  |  |  |                     } | 
		
	
		
			
				|  |  |  |  |     } | 
		
	
		
			
				|  |  |  |  |     /* apply anchored 'ends with' as depth to all patterns */ | 
		
	
		
			
				|  |  |  |  |     if (has_depth && has_ends_with) { | 
		
	
		
			
				|  |  |  |  |         for (SigMatch *sm = sm_head; sm != NULL; sm = sm->next) { | 
		
	
		
			
				|  |  |  |  |             switch (sm->type) { | 
		
	
		
			
				|  |  |  |  |                 case DETECT_CONTENT: { | 
		
	
		
			
				|  |  |  |  |                     DetectContentData *cd = (DetectContentData *)sm->ctx; | 
		
	
		
			
				|  |  |  |  |                     if (cd->depth == 0) | 
		
	
		
			
				|  |  |  |  |                         cd->depth = ends_with_depth; | 
		
	
		
			
				|  |  |  |  |                     cd->depth = MIN(ends_with_depth, cd->depth); | 
		
	
		
			
				|  |  |  |  |                     if (cd->depth) | 
		
	
		
			
				|  |  |  |  |                         cd->flags |= DETECT_CONTENT_DEPTH; | 
		
	
		
			
				|  |  |  |  |                     break; | 
		
	
		
			
				|  |  |  |  |                 } | 
		
	
		
			
				|  |  |  |  |             } | 
		
	
		
			
				|  |  |  |  |         } | 
		
	
	
		
			
				
					|  |  |  | @ -696,6 +692,14 @@ void DetectContentPropagateLimits(Signature *s) | 
		
	
		
			
				|  |  |  |  | #undef VALIDATE | 
		
	
		
			
				|  |  |  |  | } | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | void DetectContentPropagateLimits(Signature *s) | 
		
	
		
			
				|  |  |  |  | { | 
		
	
		
			
				|  |  |  |  |     for (uint32_t list = 0; list < s->init_data->smlists_array_size; list++) { | 
		
	
		
			
				|  |  |  |  |         SigMatch *sm = s->init_data->smlists[list]; | 
		
	
		
			
				|  |  |  |  |         PropagateLimits(s, sm); | 
		
	
		
			
				|  |  |  |  |     } | 
		
	
		
			
				|  |  |  |  | } | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | static inline bool NeedsAsHex(uint8_t c) | 
		
	
		
			
				|  |  |  |  | { | 
		
	
		
			
				|  |  |  |  |     if (!isprint(c)) | 
		
	
	
		
			
				
					|  |  |  | 
 |